Cod sursa(job #1048331)

Utilizator MancasAlinaMancas Alina MancasAlina Data 5 decembrie 2013 18:58:55
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.58 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;
}