Cod sursa(job #1014727)

Utilizator cahemanCasian Patrascanu caheman Data 23 octombrie 2013 08:56:43
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.36 kb
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

char sir[20][30005];
char sol[600000];
int potriv[20][20], pi[20][30005], d[(1 << 18) + 5][20], tata[(1 << 18) + 5][20];
int lung[20], vaux[20];
int n, first;

void kmpuri()
{
  int i, j, k;
  for(i = 1; i <= n; ++ i)
  {
    k = 0;
    for(j = 2; j <= lung[i]; ++ j)
    {
      while(sir[i][k + 1] != sir[i][j] && k > 0)
      {
        k = pi[i][k];
      }
      if(sir[i][k + 1] == sir[i][j])
      {
        ++ k;
        pi[i][j] = k;
      }
      else
        pi[i][j] = 0;
    }
  }
}

void potriviri()
{
  int i, j, k, l;
  for(i = 1; i <= n; ++ i)
    for(j = 1; j <= n; ++ j)
      if(j != i)
      {
        k = 0;
        for(l = 1; l <= lung[j]; ++ l)
        {
          while(sir[i][k + 1] != sir[j][l] && k > 0)
          {
            k = pi[i][k];
          }
          if(sir[i][k + 1] == sir[j][l])
            ++ k;
          if(k == lung[i] && l < lung[j])
          {
            first = first | (1 << (i - 1));
            k = 0;
            break;
          }
        }
        potriv[j][i] = k;
      }
}

int main()
{
  freopen("adn.in", "r", stdin);
  freopen("adn.out", "w", stdout);
  int i, j, l, lim, last, pc, nrsol = 0;
  scanf("%d\n", &n);
  lim = 1 << n;
  for(i = 1; i <= n; ++ i)
  {
    gets(sir[i] + 1);
    lung[i] = strlen(sir[i] + 1);
  }
  kmpuri();
  potriviri();
  for(i = 0; i < lim; ++ i)
    for(j = 0; j <= n; ++ j)
      d[i][j] = 700000;
  d[first][0] = 0;
  for(i = 0; i < lim; ++ i)
  {
      for(j = 0; j < n; ++ j)
        vaux[j + 1] = ((i >> j) & 1);
      for(j = 0; j <= n; ++ j)
      {
        for(l = 1; l <= n; ++ l)
        if(! vaux[l])
        {
          if(d[i][j] + lung[l] - potriv[j][l] < d[i | (1 << (l - 1))][l])
          {
            d[i | (1 << (l - 1))][l] = d[i][j] + lung[l] - potriv[j][l];
            tata[i | (1 << (l - 1))][l] = l;
          }
        }
      }
  }
  last = 1;
  for(i = 1; i <= n; ++ i)
    if(d[lim - 1][i] < d[lim - 1][last])
      last = i;
  pc = lim - 1;
  while(pc != first)
  {
    pc = tata[pc][last];
    for(i = lung[last]; i > potriv[pc][last]; -- i)
      sol[++ nrsol] = sir[last][i];
    pc -= (1 << (pc - 1));
    last = pc;
  }
  for(i = nrsol; i >= 1; -- i)
    printf("%c", sol[i]);
  return 0;
}