Cod sursa(job #177338)

Utilizator savimSerban Andrei Stan savim Data 12 aprilie 2008 18:36:11
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.21 kb
#include <stdio.h>
#include <string.h>
#define maxl 30010
#define inf 2147000000
#define put2 262250

int i,j,k,t,n,x,max,o,poz;
char s[20][maxl];
int pref[20][maxl];
int kmp[20][20];
int fol[20],used[20];
int c[20][put2];
int l[20];

int main()
{
    freopen("adn.in","r",stdin);
	freopen("adn.out","w",stdout);
    
    scanf("%d",&n);
	for (i=1; i<=n; i++)
    {
        scanf("%s",s[i]+1);
        s[i][0]=' ';
        l[i]=strlen(s[i])-1;
    }
    
    for (i=1; i<=n; i++)
	{
		x=0;k=l[i]-1;
		for (j=2; j<=k; j++)
		{
			while (s[i][x+1]!=s[i][j] && x) x=pref[i][x];
			if (s[i][x+1]==s[i][j])
			{
			   x++;
			   pref[i][j]=x;
			}
		}
	}

	for (i=1; i<=n; i++) fol[i]=1;

	for (i=1; i<=n; i++)
		for (j=1; j<=n; j++)
		if (i!=j)
		{
			x=0;max=0;
			k=l[j];o=l[i]-1;
			for (t=1; t<=k; t++)
			{
				while (s[i][x+1]!=s[j][t] && x) x=pref[i][x];
				if (s[i][x+1]==s[j][t])
				{
					x++;
					if (x>max && t==k) max=x;
					if (x==o) fol[i]=0;
				}
            }
            kmp[i][j]=max;
        }


	for (j=1; j<=(1<<n)-1; j++)
		for (i=1; i<=n; i++)
			c[i][j]=inf;

	for (i=1; i<=n; i++)
		if (fol[i]) c[i][1<<(i-1)]=l[i];

	for (j=1; j<=(1<<n)-1; j++)
		for (i=1; i<=n; i++)
			if (fol[i] && (j&(1<<(i-1))) && c[i][j]!=inf)
			for (t=1; t<=n; t++)
			if (fol[t] && !(j&(1<<(t-1))) )
			{
				o=l[t];
				if (c[t][j+(1<<(t-1))]>c[i][j]+o-kmp[t][i])
					c[t][j+(1<<(t-1))]=c[i][j]+o-kmp[t][i];
			}

	o=0;
	for (i=1; i<=n; i++)
		o=o+fol[i]*(1<<(i-1));

	k=inf;
	for (i=1; i<=n; i++)
		if (c[i][o]<k)
		{
			k=c[i][o];
			poz=i;
		}

//	printf("%d %d\n",k,poz);

	for (i=1; i<=n; i++)
	{
		if (!fol[i]) used[i]=1;
		fol[i]=0;
	}

	x=1;used[poz]=1;
	fol[x]=poz;
	while (o-(1<<(poz-1)) >0)
	{
		x++;
		o=o-(1<<(poz-1));
		for (i=1; i<=n; i++)
		if (!used[i])
		{
			t=l[poz];
			if (c[poz][o+(1<<(poz-1))]==c[i][o]+t-kmp[poz][i])
			{
				poz=i;
				used[i]=1;
				fol[x]=poz;
				break;
			}
		}
	}

	for (i=1; i<=x>>1; i++)
	{
		o=fol[x+1-i];
		fol[x+1-i]=fol[i];
		fol[i]=o;
	}

	printf("%s",s[fol[1]]+1);
	for (i=2; i<=x; i++)
		printf("%s",s[fol[i]]+kmp[fol[i]][fol[i-1]]+1);
	printf("\n");

	return 0;
}