Cod sursa(job #430959)

Utilizator indestructiblecont de teste indestructible Data 31 martie 2010 15:01:54
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.11 kb
#include <stdio.h>
#define NMAX 20
#define LMAX 30010
#define HMAX 1<<18
#define INF 1000000000
char A[NMAX][LMAX],marc[NMAX];
int n,L[NMAX],D[NMAX][NMAX],pi[LMAX],match,pot;
int B[NMAX],best[NMAX][HMAX],st,h,rez=INF,poz,ant[NMAX][HMAX];
inline int ok(char x)
{
	return x=='A' || x=='G' || x=='C' || x=='T';
}
void read()
{
	scanf("%d\n",&n);
	int i;
	for (i=1; i<=n; i++)
	{
		fgets(A[i]+1,LMAX,stdin);
		while (ok(A[i][L[i]+1]))
			L[i]++;
	}
}
void prefix(int x)
{
	int k=0,i;
	for (i=2; i<=L[x]; i++)
	{
		while (k>0 && A[x][k+1]!=A[x][i])
			k=pi[k];
		if (A[x][k+1]==A[x][i])
			k++;
		pi[i]=k;
	}
}
void kmp(int x,int y)
{
	int i,q=0;
	for (i=1; i<=L[x]; i++)
	{
		while  (q>0 && A[y][q+1] != A[x][i]) 
			q=pi[q];
		if ( A[y][q+1] == A[x][i]) 
			q++;
		if (q==L[y])
			pot=1;
		match=q;
	}
}
void prepare()
{
	int i,j;
	for (i=1; i<=n; i++)
		for (j=1; j<=n; j++)
			if (i!=j)
			{
				prefix(j);
				match=pot=0;
				kmp(i,j);
				if (pot)
					marc[j]=1;
				D[i][j]=match;
			}
}
void get_valid()
{
	int i;
	for (i=1; i<=n; i++)
		if (!marc[i])
			B[++st]=i;
	h=(1<<st)-1;
}
void init()
{
	int i,j;
	for (i=1; i<=st; i++)
		for (j=1; j<=h; j++)
			best[i][j]=INF;
	for (i=1; i<=st; i++)
		best[i][1<<(i-1)]=L[B[i]];
}
void solve()
{
	int i,j,k,t;
	for (j=0; j<=h; j++)
		for (i=1; i<=st; i++)
			if (j & 1<<(i-1))
			{
				for (k=1; k<=st; k++)
					if (!(j & 1<<(k-1)))
					{
						t=j ^ 1<<(k-1);
						if (best[k][t] > best[i][j]+L[B[k]]-D[B[i]][B[k]])
							best[k][t]=best[i][j]+L[B[k]]-D[B[i]][B[k]],ant[k][t]=i;
					}
			}
}
void get_sol()
{
	int i;
	for (i=1; i<=st; i++)
		if (best[i][h]<rez)
			rez=best[i][h],poz=i;
}
void reconst(int poz,int stare)
{
	if (stare==0)
		return ;
	int i,poz2=ant[poz][stare],stare2=stare ^ 1<<(poz-1);
	reconst(poz2,stare2);
	for (i=D[B[poz2]][B[poz]]+1; i<=L[B[poz]]; i++)
		printf("%c",A[B[poz]][i]);
}
int main()
{
	freopen("adn.in","r",stdin);
	freopen("adn.out","w",stdout);
	read();
	prepare();
	get_valid();
	init();
	solve();
	get_sol();
	reconst(poz,h);
	return 0;
}