Cod sursa(job #6595)
#include<stdio.h>
#include<string.h>
typedef struct nod { int x; nod *d; } nod;
nod *w[20];
int p[31000],OK,n,ok[20],v[20][20],qq[300000][20];
char s[20][31000];
long q[300000][20];
void init(int x)
{ int i,n,k,q;
n=strlen(s[x])-1;
for(i=0;i<=n;i++) p[i]=-1;
n=strlen(s[x])-1;
k=-1;
for(q=1;q<=n;q++)
{
while(k>=0 && s[x][k+1]!=s[x][i])
k=p[k];
if(s[x][k+1]==s[x][q]) q++;
p[q]=k;
}
}
int find(int x,int y)
{ OK=0;
int n,m,q,i;
m=strlen(s[x])-1;
n=strlen(s[y])-1;
q=-1;
for(i=0;i<=n;i++)
{
while(q>=0 && s[x][q+1]!=s[y][i])
q=p[q];
if(s[x][q+1]==s[y][i]) q++;
if(q==m) { q=p[q]; OK=1; }
}
return q+1;
}
void READ()
{ int i,j,x,y;
FILE *f;
f=fopen("adn.in","r");
fscanf(f,"%d",&n);
for(i=1;i<=n;i++)
fscanf(f,"%s",&s[i]);
for(i=1;i<=n;i++)
{ init(i);
for(j=1;j<=n;j++)
if(ok[j]==0 && i!=j)
{
v[i][j]=find(i,j);
ok[i]=ok[i]||OK;
}
}
x=0; y=0;
for(i=1;i<=n;i++)
{
if(ok[i]==0)
{ x++; y=0;
for(j=1;j<=n;j++)
if(ok[j]==0) {
y++;
v[x][y]=v[i][j]; }
}
}
for(i=1;i<=n;i++)
if(ok[i]==1)
{ for(j=i+1;j<=n;j++)
{ strcpy(s[j-1],s[j]);
ok[j-1]=ok[j];
}
n--;}
fclose(f);
}
long maxim(long x,int k)
{ long max=-1,i;
for(i=1;i<=n;i++)
if(i!=k && x&(1<<(i-1)) && max< q[x - ((1<<(k-1)))][i]+v[i][k]) {
max= (q[x -(1<<(k-1))][i]+v[i][k]);
qq[x][k]=i; }
return max;
}
void SOLVE()
{ long i,x,j;
nod *p;
for(i=1;i<(1<<n);i++)
{
x=0;
j=i;
while(j)
{
x++;
j=j&(j-1);
}
p=new nod;
p->x=i;
p->d=w[x];
w[x]=p;
}
for(x=2;x<=n;x++)
{
p=w[x];
while(p)
{
for(i=1;i<=n;i++)
if(p->x & (1<<(i-1))) q[p->x][i]=maxim(p->x,i);
p=p->d;
}
}
}
void PRINT()
{ int i,j,jj;
long x;
FILE *g;
g=fopen("adn.out","w");
j=1;
for(i=1;i<=n;i++)
if(q[(1<<n)-1][i]>q[(1<<n)-1][j]) j=i;
x=(1<<n)-1;
while(x)
{ for(i=0;i<strlen(s[j])-(v[qq[x][j]][j]);i++)
fprintf(g,"%c",s[j][i]);
jj=j;
j=qq[x][j];
x=x - (1<<(jj-1));
}
fclose(g);
}
int main()
{
READ();
SOLVE();
PRINT();
return 0;
}