Cod sursa(job #65822)

Utilizator sealTudose Vlad seal Data 13 iunie 2007 11:22:05
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.78 kb
#include<stdio.h>
#include<string.h>
#define Nm 18
#define Lm 30002
char S1[Nm][Lm],S2[Nm][Lm],S[Nm*Lm];
int M[1<<Nm][Nm],N[1<<Nm][Nm],C[Nm][Nm],Pi[Lm],L[Nm],n;

void read()
{
    int i;

    freopen("adn.in","r",stdin);
    scanf("%d\n",&n);
    for(i=0;i<n;++i)
	gets(S1[i]+1);
}

void prefix(char P[], int n)
{
    int i,k;

    k=Pi[1]=0;
    for(i=2;i<=n;++i)
    {
	while(k && P[k+1]!=P[i])
	    k=Pi[k];
	if(P[k+1]==P[i])
	    ++k;
	Pi[i]=k;
    }
}

int KMP1(char P[], int n, char T[], int m)
{
    int i,k=0;

    for(i=1;i<m;++i)
    {
	while(k && P[k+1]!=T[i])
	    k=Pi[k];
	if(P[k+1]==T[i])
	    ++k;
	if(k==n)
	    return 1;
    }
    return 0;
}

int KMP2(char P[], char T[], int m)
{
    int i,k=0;

    for(i=1;i<=m;++i)
    {
	while(k && P[k+1]!=T[i])
	    k=Pi[k];
	if(P[k+1]==T[i])
	    ++k;
    }
    return k;
}


void solve()
{
    int i,j,k=0;

    for(i=0;i<n;++i)
	L[i]=strlen(S1[i]+1);

    for(i=0;i<n;++i)
    {
	prefix(S1[i],L[i]);
	for(j=0;j<n && !KMP1(S1[i],L[i],S1[j],L[j]);++j);
	if(j==n)
	{
	    strcpy(S2[k]+1,S1[i]+1);
	    L[k++]=L[i];
	}
    }
    n=k;

    for(i=0;i<n;++i)
    {
	prefix(S2[i],L[i]);
	for(j=0;j<n;++j)
	    C[i][j]=KMP2(S2[i],S2[j],L[j]);
    }

    for(i=1;i<1<<n;++i)
	for(j=0;j<n;++j)
	    for(k=0;k<n;++k)
		if(1<<k&i && C[k][j]+M[i-(1<<k)][k]>M[i][j])
		{
		    M[i][j]=C[k][j]+M[i-(1<<k)][k];
		    N[i][j]=k;
		}

    i=(1<<n)-1; j=0;
    for(k=1;k<n;++k)
	if(M[i][k]>M[i][j])
	    j=k;
    strcpy(S,S2[j]+1);
    while(i)
    {
	k=N[i][j];
	strcat(S,S2[k]+C[k][j]+1);
	i-=1<<k; j=k;
    }
}

void write()
{
    freopen("adn.out","w",stdout);
    printf("%s\n",S);
}

int main()
{
    read();
    solve();
    write();
    return 0;
}