Cod sursa(job #848570)

Utilizator SebiSebiPirtoaca George Sebastian SebiSebi Data 5 ianuarie 2013 16:41:43
Problema ADN Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.61 kb
#include<iostream>
#include<fstream>
#include<vector>
#include<string.h>
using namespace std;

#define NMAX 19
#define LMAX 30005

ofstream g("adn.out");

struct muchie {
	int cost,y;
};

vector <muchie> v[NMAX];
int l[LMAX],r[NMAX],d[NMAX][(1<<NMAX)+1],nod[NMAX][(1<<NMAX)+1],a[NMAX][NMAX];
char c[NMAX][LMAX];

inline void prefix(char s[], int n)
{
	int i,k;
	l[1]=0;
	for(i=2;i<=n;i++) {
		k=l[i-1];
		while(k && s[k+1]!=s[i])
			k--;
		if(s[k+1]==s[i])
			k++;
		l[i]=k;
	}
}

inline int KMP(char s[], char  p[])
{
	int i,k,n,m;
	n=strlen(s+1);
	m=strlen(p+1);
	prefix(p,m);
	k=0;
	for(i=1;i<=n;i++) {
		while(k && p[k+1]!=s[i])
			k=l[k];
		if(p[k+1]==s[i])
			k++;
		if(k==m) 
			return 1;
	}
	return 0;
}

inline void remove(int n)
{
	int i,j;
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			if(r[j]==0 && i!=j) {
				if(KMP(c[j],c[i])) {
					r[i]=1;
					break;
				}
			}
}

inline int KMP2(char s[], char p[])
{
	int i,k,n,m;
	n=strlen(s+1);
	m=strlen(p+1);
	k=0;
	for(i=1;i<=n;i++) {
		while(k && s[i]!=p[k+1])
			k=l[k];
		if(s[i]==p[k+1])
			k++;
	}
	return k;
}

inline void builtgraph(int n)
{
	int i,j;
	muchie x;
	for(i=1;i<=n;i++) {
		if(r[i]==1)
			continue;
		prefix(c[i],strlen(c[i]+1));
		for(j=1;j<=n;j++)
			if(i!=j && r[j]==0) {
				x.y=j;
				x.cost=KMP2(c[j],c[i]);
				v[i].push_back(x);
				a[i][j]=x.cost;
			}
	}
}

inline int BIT(int nr, int i)
{
	return (nr & (1<<i))!=0;
}

inline void dp(int n)
{
	int i,s;
	for(s=6;s<=(1<<(n+1))-1;s++) {
		for(i=1;i<=n;i++)
			if(s-1==(1<<i))
				break;
		if(i<=n)
			continue;
		for(i=1;i<=n;i++)
			if(r[i]==0 && BIT(s,i)) {
				for(vector <muchie> :: iterator it=v[i].begin();it!=v[i].end();it++) {
					if(s-(1<<i)<=0)
						continue;
					if(d[i][s]<=d[it->y][s-(1<<i)]+it->cost && BIT(s-(1<<i),it->y)) {
						d[i][s]=d[it->y][s-(1<<i)]+it->cost;
						nod[i][s]=it->y;
					}
				}
			}
	}
}

inline void afisare(int i, int s)
{
	if((1<<i)+1==s || i<=0) {
		g<<c[i]+1;
		return;
	}
	int x;
	x=nod[i][s];
	afisare(x,s-(1<<i));
	g<<c[i]+a[i][x]+1;
}
	
int main ()
{
	int i,n,cost,x,s;
	ifstream f("adn.in");
	f>>n;
	for(i=1;i<=n;i++) {
		f>>(c[i]+1);
		c[i][0]=' ';
	}
	f.close();
	remove(n);
	x=0;
	for(i=1;i<=n;i++)
		if(r[i]==0)
			x++;
	if(x==1) {
		for(i=1;i<=n;i++)
			if(r[i]==0)
				break;
		g<<c[i]+1;
		g<<'\n';
		g.close();
		return 0;
	}
	builtgraph(n);
	dp(n);
	cost=-1;
	s=(1<<(n+1))-1;
	for(i=1;i<=n;i++)
		if(r[i]==0 && d[i][s]>cost) {
			cost=d[i][s];
			x=i;
		}
	afisare(x,s);
	g<<'\n';
	g.close();
	return 0;
}