Pagini recente » Cod sursa (job #1590189) | Cod sursa (job #1505763) | Cod sursa (job #642206) | Cod sursa (job #1610883) | Cod sursa (job #1803742)
#include <bits/stdc++.h>
using namespace std;
#define FILE_IO
typedef pair<int, int> pii;
int mod[] = {(int)1e9 + 7, (int) 1e9 + 9};
int base[] = {7, 5};
int N, B;
int b[20];
char s[20][30005];
int cmn[20][20];
int dp[270005][20];
int lst[270005][20];
int lg2[270005];
int p[270005][2];
int l[20];
vector <int> ord;
int M;
int f[20];
int need[20];
int hsh[20][30005][2];
int getval(char ch)
{
if(ch == 'A') return 1;
if(ch == 'G') return 2;
if(ch == 'C') return 3;
if(ch == 'T') return 4;
return 0;
}
pii HASH(int id, int st, int dr)
{
int h[2];
for(int k = 0; k <= 1; k++)
h[k] = (hsh[id][dr][k] - (1LL * hsh[id][st - 1][k] * p[dr - st + 1][k]) % mod[k] + mod[k]) % mod[k];
return {h[0], h[1]};
}
int main()
{
#ifdef FILE_IO
freopen("adn.in", "r", stdin);
freopen("adn.out", "w", stdout);
#endif
scanf("%d\n", &N);
for(int i = 0; i < N; i++)
{
gets(s[i] + 1);
l[i] = strlen(s[i] + 1);
for(int j = 1; j <= l[i]; j++)
{
int x = getval(s[i][j]);
for(int k = 0; k <= 1; k++)
hsh[i][j][k] = ( (1LL * hsh[i][j - 1][k] * base[k]) % mod[k] + x ) % mod[k];
}
}
for(int k = 0; k <= 1; k++)
{
p[0][k] = 1;
for(int i = 1; i <= 30000; i++)
p[i][k] = (1LL * p[i - 1][k] * base[k]) % mod[k];
}
for(int i = 0; i < N; i++)
f[i] = 1;
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
if(i == j) continue;
if(l[j] < l[i]) continue;
for(int k = 1; k + l[i] - 1 <= l[j]; k++)
if( HASH(i, 1, l[i]) == HASH(j, k, k + l[i] - 1) )
{
f[i] = 0;
break;
}
if(!f[i]) break;
}
}
for(int i = 0; i < N; i++)
if(f[i])
need[M++] = i;
for(int i = 0; i < N; i++)
{
if(!f[i]) continue;
for(int j = 0; j < N; j++)
{
if(!f[j]) continue;
if(i == j)
{
cmn[i][j] = l[i];
continue;
}
cmn[i][j] = 0;
for(int k = min(l[i], l[j]); k >= 1; k--)
{
pii h1 = HASH(i, l[i] - k + 1, l[i]);
pii h2 = HASH(j, 1, k);
if( h1 == h2 )
{
cmn[i][j] = k;
break;
}
}
}
}
for(int i = 2; i <= 1 << M; i++)
{
lg2[i] = lg2[i - 1];
if( (2 << lg2[i]) == i )
lg2[i]++;
}
for(int msk = 1; msk < 1 << M; msk++)
{
if( !(msk & (msk - 1)) )
{
dp[msk][ lg2[msk] ] = l[ need[ lg2[msk] ] ];
lst[msk][ lg2[msk] ] = 0;
continue;
}
int aux = msk;
B = 0;
while(aux)
{
b[ ++B ] = lg2[aux];
aux -= 1 << lg2[aux];
}
for(int ii = 1, i = b[ii]; ii <= B; ii++, i = b[ii])
{
dp[msk][i] = 1 << 30;
for(int jj = 1, j = b[jj]; jj <= B; jj++, j = b[jj])
{
if(ii == jj) continue;
if(dp[msk][i] > dp[msk ^ (1 << i)][j] + l[ need[i] ] - cmn[ need[j] ][ need[i] ])
{
dp[msk][i] = dp[msk ^ (1 << i)][j] + l[ need[i] ] - cmn[ need[j] ][ need[i] ];
lst[msk][i] = j;
}
}
}
}
int ans = 1 << 30;
int id = -1;
int msk = (1 << M) - 1;
for(int i = 0; i < M; i++)
if(dp[msk][i] < ans)
{
ans = dp[msk][i];
id = i;
}
while(msk)
{
ord.push_back(need[id]);
int newid = lst[msk][id];
msk ^= 1 << id;
id = newid;
}
reverse(ord.begin(), ord.end());
printf("%s", s[ ord[0] ] + 1);
for(int i = 1; i < ord.size(); i++)
{
for(int j = 1 + cmn[ ord[i - 1] ][ ord[i] ]; j <= l[ ord[i] ]; j++)
printf("%c", s[ ord[i] ][j]);
}
printf("\n");
return 0;
}