Cod sursa(job #34686)

Utilizator m_dersidanDersidan Mihai m_dersidan Data 21 martie 2007 10:38:51
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.17 kb
# include <stdio.h>
# include <string.h>

# define  _fin  "adn.in"
# define  _fout "adn.out"

# define  maxn	20
# define  maxw	30003
# define  pow2n 262244


int c[maxn][maxn], out[maxn], n;
char w[maxn][maxw];
int a[maxn][pow2n], f[maxn][pow2n];
int sol[maxn];

void readf()
{
	freopen(_fin, "r", stdin);
	scanf("%d\n", &n);
	for (int i=1; i<=n; i++)
		scanf("%s\n", w[i]),
		memmove(w[i]+1, w[i], sizeof(w[i])), w[i][0]='0';
}

int p[maxw];

int kmp(int a, int b, int &match)
{
	int k=0, i, to=strlen(w[b]);
	memset(p, 0, sizeof(p));
	
	for (i=2; i<to; i++)
	{
		while ( k>0 && w[b][k+1] != w[b][i] ) k=p[k];
		k += ( w[b][k+1]==w[b][i] );
		p[i]=k;
	}
	
	for (i=1, to=strlen(w[a]); i<to; i++)
	{
		while ( k>0 && w[b][k+1] != w[a][i] ) k=p[k];
		k += ( w[b][k+1]==w[a][i] );
		if ( k==strlen(w[b])-1 ) {
			match=strlen(w[b])-1;
			return 1;
		}
	}
	match=k;
	
	return 0;
}

void presolve()
{
	// precalculate N and C
	int i, j, foo;
	
	// first, take out all words that we don't need
	for (i=1; i<=n; i++)
		for (j=1; j<=n; j++)
		{
			if ( i==j ) continue;
			if ( kmp(i, j, foo) )
				out[j]=1;
		}

	for (i=n; i>=1; i--)
		if ( out[i] )
			memcpy(w[i], w[n], sizeof(w[n])), n--;

	for (i=1; i<=n; i++)
		for (j=1; j<=n; j++)
		{
			if ( i==j ) continue;
			kmp(i, j, c[i][j]);
		}
}

void solve()
{
	int i, j, k, l, to=(1<<n)-1;
	
	memset(a, 0xff, sizeof(a));
	for (i=1; i<=n; i++) a[i][1<<(i-1)]=0;
	
	for (i=3; i<=to; i++)
		for (j=1; j<=n; j++) {
			if ( !(i & (1<<(j-1))) ) continue;
			
			for (k=1; k<=n; k++)
				if ( i & (1<<(k-1)) )
					if ( c[j][k] + a[k][ i ^ (1<<(j-1)) ] > a[j][i] )
						a[j][i] = c[j][k] + a[k][i^(1<<(j-1))], f[j][i]=k;
		}
	
	int max=1;
	for (i=2; i<=n; i++)
		if ( a[i][to] > a[max][to] ) max=i;
	
	for (i=max, j=to; f[i][j]; k=i, i=f[i][j], j^=(1<<(k-1)))
		sol[ ++sol[0] ] = i;
	sol[ ++sol[0] ] = i;
}

void writef()
{
	freopen(_fout, "w", stdout);
	int i;
	for (printf("%s", w[sol[1]]+1), i=2; i<=sol[0]; i++)
		 printf("%s", w[sol[i]] + c[sol[i-1]][sol[i]]+1);
	
	printf("\n");
}

int main()
{
	readf();
	presolve();
	solve();
	writef();

	return 0;
}