Pagini recente » Cod sursa (job #361070) | Cod sursa (job #1497338) | Cod sursa (job #851480) | Cod sursa (job #3199532) | Cod sursa (job #195656)
Cod sursa(job #195656)
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
const int maxN = 18;
const int maxC = 32002;
const int maxCD = 2400000;
const int modH = 666013;
const int bzH = 19;
int N;
int dMin[ (1<<18) ][ 18 ];
int parent[ (1<<18) ][ 18 ];
char str[ maxN ][ maxC ];
int ln[ maxN ];
int power[ maxC ];
int solOrd[ maxN ];
int supp[ maxN ][ maxN ];
int lC;
long long hash1, hash2;
int powF( int bz, int exp ) {
long long rez = 1;
long long aux = bz;
for ( int i = 0; i < 16; i++ ) {
if ( exp & ( 1 << i ) )
rez = ( rez * aux ) % modH;
aux = ( aux * aux ) % modH;
}
return (int) rez;
}
bool eok( int X, int K ) {
int R = 0;
for ( int i = 0; i < maxN; i++ )
if ( (1<<i) & K ) R++;
return ( R == X );
}
int main()
{
#ifndef PC_COMPILE
freopen("adn.in","r",stdin);
freopen("adn.out","w",stdout);
#endif
#ifdef PC_COMPILE
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif
scanf("%d\n", &N );
for ( int i = 0; i < N; i++ ) {
scanf("%s\n", str[ i ] );
ln[i] = strlen( str[i] );
}
for ( int i = 0; i < 30001; i++ )
power[ i ] = powF( bzH, i );
int M =0;
for ( int i = 0; i < N; i++ ) {
hash1 = 0;
for ( int j = 0; j < ln[i]; j++ )
hash1 = ( hash1 + str[i][j]*power[ln[i]-(j+1)] ) % modH;
int ins = 1;
for ( int j = 0 && ins; j < N; j++ )
if ( ln[i] <= ln[j] && i != j) {
hash2 = 0;
for ( int k = 0; k < ln[i]; k++ )
hash2 = ( hash2 + str[j][k]*power[ln[i]-(k+1)] ) % modH;
if ( hash1 == hash2 ) {
ins = 0;
for ( int k = 0; k < ln[i]; k++ )
if ( str[i][k] != str[j][k] ) ins = 1;
if ( !ins ) break;
}
for ( int k = ln[i]; k < ln[j]; k++ ) {
hash2 = ( hash2 + 100*modH - str[j][k-ln[i]]*power[ ln[i]-1 ] ) % modH;
hash2 = ( hash2 * bzH + str[j][k] ) % modH;
if ( hash2 == hash1 ) {
ins = 0;
for ( int l = k-ln[i]+1; l <= k; l++ )
if ( str[j][l] != str[i][l-k+ln[i]-1] ) ins = 1;
if ( !ins ) break;
}
}
}
if ( ins ) {
solOrd[M] = i;
M++;
}
}
N = M;
for ( int i = 0; i < N; i++ ) {
ln[ i ] = ln[ solOrd[i] ];
memcpy( str[i], str[ solOrd[i] ], sizeof( str[i] ) );
dMin[(1<<i)][i] = ln[i];
}
for ( int i = 0; i < N; i++ )
for ( int j = 0; j < N; j++ ) {
hash1 = 0, hash2 = 0;
for ( int l = 1; l <= min( ln[i], ln[j] ); l++ ) {
hash1 = ( hash1 + str[i][ ln[i] - l ]*power[ l-1] ) % modH;
hash2 = ( hash2*bzH + str[j][ l-1 ] ) % modH;
if ( hash1 == hash2 )
supp[i][j] = l;
}
}
for ( int i = 0; i < (1<<N); i++ )
for ( int j = 0; j < N; j++ )
if ( dMin[i][j] != 0 ) {
//printf("[%d][%d] = %d (%d)\n", i, j, dMin[i][j], parent[i][j] );
for ( int k = 0; k < N; k++ ) {
if ( ! (i&(1<<k) ) )
if ( dMin[ i + (1<<k) ][ k ] > dMin[i][j] + ln[k] - supp[j][k] || !dMin[i+(1<<k)][k] ) {
dMin[i+(1<<k)][k] = dMin[i][j]+ln[k]-supp[j][k];
parent[i+(1<<k)][k] = j;
}
}
}
int sol = 0;
int cfg = (1<<N)-1;
for ( int i = 1; i < N; i++ )
if ( dMin[cfg][sol] > dMin[cfg][i] )
sol = i;
int i = N-1;
while ( i >= 0 ) {
solOrd[i] = sol;
sol = parent[ cfg ][ sol ];
cfg -= ( 1 << solOrd[i] );
i--;
}
solOrd[N] = N;
for ( int i = 0; i < N; i++ ) {
for ( int j = 0; j < ln[ solOrd[i] ] - supp[ solOrd[i] ][ solOrd[i+1] ]; j++ )
printf("%c", str[ solOrd[i] ][ j ] );
}
printf("\n");
return 0;
}