Cod sursa(job #464004)

Utilizator AndreyPAndrei Poenaru AndreyP Data 18 iunie 2010 13:23:17
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.49 kb
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define N 18
#define L 30005

int n;
char c[N][L];
int pi[N][L];
int lun[N];
int cost[N][N];
int a[1<<N][N];
int ind[N];
int pre[1<<N][N];

inline int len(char *p)
{
	int i=1;
	for(i=1; p[i]>='A' && p[i]<='Z'; ++i)
		;
	p[i]='\0';
	return i-1;
}

inline void citire()
{
	scanf("%d\n",&n);
	for(int i=0; i<n; ++i)
	{
		fgets(c[i]+1,L-1,stdin);
		lun[i]=len(c[i]);
	}
}

bool compar(const int &x,const int &y)
{
	if(lun[x]>lun[y])
		return true;
	return false;
}

inline void precalcPi(int k)
{
	pi[k][1]=0;
	int q=0;
	for(int i=2; i<=lun[k]; ++i)
	{
		while(q>0 && c[k][q+1]!=c[k][i])
			q=pi[k][q];
		if(c[k][q+1]==c[k][i])
			++q;
		pi[k][i]=q;
	}
}

inline bool apartine(int k,int t)
{
	int q=0;
	for(int i=1; i<=lun[t]; ++i)
	{
		while(q>0 && c[t][i]!=c[k][q+1])
			q=pi[k][q];
		if(c[t][i]==c[k][q+1])
			++q;
		if(q==lun[k])
			return true;
	}

	cost[t][k]=q;
	for(int i=1; i<=lun[k]; ++i)
	{
		while(q>0 && c[k][i]!=c[t][q+1])
			q=pi[t][q];
		if(c[k][i]==c[t][q+1])
			++q;
	}
	cost[k][t]=q;
	return false;
}

inline void precalc()
{
	for(int i=0; i<n; ++i)
	{
		ind[i]=i;
		precalcPi(i);
	}
	sort(ind,ind+n,compar);
	for(int i=n-1; i>=0; --i)
	{
		for(int j=i-1; j>=0; --j)
		{
			if(apartine(ind[i],ind[j]))
			{
				ind[i]=ind[n-1];
				--n;
				break;
			}
		}
	}
}

void scrie(int lim,int x)
{
	if(pre[lim][x]==-1)
	{
		fputs(c[ind[x]]+1,stdout);
		return;
	}

	scrie(lim^(1<<x),pre[lim][x]);
	fputs(c[ind[x]]+1+cost[ind[pre[lim][x]]][ind[x]],stdout);
}

inline void rezolva()
{
	for(int i=0; i<n; ++i)
		pre[1<<i][i]=-1;
	if(n>N)
		exit(4);

	int lim=1<<n;
	int x;
	int aux,caux=-1;
	for(int i=1; i<lim; ++i)
	{
		for(int j=0; j<n; ++j)
		{
			if((i&(1<<j))==0)
				continue;
			x=i^(1<<j);
			aux=0;
			caux=-1;
			for(int t=1,k=0; t<=x; t<<=1,++k)
			{
				if((t&x)==0)
					continue;
				aux=a[x][k]+cost[ind[k]][ind[j]];
				caux=k;
				if(a[i][j]<aux)
				{
					a[i][j]=aux;
					pre[i][j]=caux;
				}
			}
		}
	}

	aux=-1;
	--lim;
	for(int i=0; i<n; ++i)
	{
		if(a[lim][i]>aux)
		{
			aux=a[lim][i];
			caux=i;
		}
	}
	if(aux==-1)
	{
		fputs("Ceva nu a mers bine!\n",stdout);
		exit(4);
	}
	exit(4);

	scrie(lim,caux);
	fputc('\n',stdout);
}

int main()
{
	freopen("adn.in","r",stdin);
	freopen("adn.out","w",stdout);

	citire();
	precalc();
	rezolva();
	
	return 0;
}