Cod sursa(job #1037471)

Utilizator AnonymouslegionAnonymous Anonymouslegion Data 20 noiembrie 2013 11:52:19
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.43 kb
#include <cstdio>
#include <cstring>

#include <vector>
#include <algorithm>

using namespace std;

const int kmans = 650000;

int n, valid[20], size[20], dp[18][1 << 18], dad[18][1 << 18];
char gv[20][30005];
int graph[20][20];

int t[30005];

void prefix(int x){
  for(int i = 2; i <= size[x]; ++i){
    int p = i - 1;
    do{
      p = t[p];
      if(gv[x][i] == gv[x][p + 1]){
        t[i] = p + 1;
        break;
      }
    }while(p);
  }
}

int dps[30005];

void checkem(int x, int y){
  memset(dps, 0, sizeof(dps));
  memset(t, 0, sizeof(t));
  prefix(y);

  for(int i = 1; i <= size[x]; ++i){
    int p = dps[i - 1];

    if(gv[x][i] == gv[y][p + 1]){
      dps[i] = p + 1;
      if(dps[i] == size[y])
        valid[y] = 0;
      continue;
    }

    if(p == 0)
      continue;
    do{
      p = t[p];
      if(gv[x][i] == gv[y][p + 1]){
        dps[i] = p + 1;
        break;
      }
    }while(p);

    if(dps[i] == size[y])
      valid[y] = 0;
  }

  graph[x][y] = size[y] - dps[size[x]];
}

int main(){
  freopen("adn.in", "r", stdin);
  freopen("adn.out", "w", stdout);

  scanf("%d\n", &n);

  for(int i = 1; i <= n; ++i){
    gets(gv[i] + 1);
    valid[i] = 1;
    size[i] = strlen(gv[i] + 1);
  }

  for(int i = 1; i <= n; ++i)
    for(int j = 1; j <= n; ++j) if(j != i)
      checkem(i, j);

  vector<int> good;
  for(int i = 1; i <= n; ++i)
    if(valid[i])
      good.push_back(i);

  int lim = 1 << good.size();

  memset(dp, 1337, sizeof(dp));

  for(int i = 0; i < good.size(); ++i){
    dp[i][1 << i] = size[good[i]];
    dad[i][1 << i] = -1;
  }

  for(int i = 0; i < lim; ++i)
    for(int j = 0; j < good.size(); ++j) if(dp[j][i] <= kmans)
      for(int k = 0; k < good.size(); ++k)
        if(!(i & (1 << k)))
          if(dp[k][i + (1 << k)] > dp[j][i] + graph[good[j]][good[k]]){
            dp[k][i + (1 << k)] = dp[j][i] + graph[good[j]][good[k]];
            dad[k][i + (1 << k)] = j;
          }

  int mins = kmans, wh = -1;
  for(int i = 0; i < good.size(); ++i)
    if(dp[i][lim - 1] < mins){
      mins = dp[i][lim - 1];
      wh = i;
    }

  vector<int> ord;
  int p = lim - 1, aux;
  for(int i = 0; i < good.size(); ++i){
    ord.push_back(good[wh]);
    aux = wh;
    wh = dad[wh][p];
    p = p - (1 << aux);
  }

  int last = 1;
  for(int i = ord.size() - 1; i >= 0; --i){
    for(int j = last; j <= size[ord[i]]; ++j)
      printf("%c", gv[ord[i]][j]);
    if(i != 0)
      last = size[ord[i - 1]] - graph[ord[i]][ord[i - 1]] + 1;
  }

  return 0;
}