Cod sursa(job #308925)

Utilizator Magnuscont cu nume gresit sau fals Magnus Data 28 aprilie 2009 21:57:44
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.45 kb
 # include <stdio.h>      
# include <string>      
     
using namespace std;      
     
# define FIN "adn.in"      
# define FOUT "adn.out"      
# define MAXL 30001      
# define MAXN 20      
# define MAXM 1<<18      
     
int N,i,j,k,maxq,mn,mx,f;      
int Prefix[MAXL];      
int C[MAXN][MAXN];      
int D[MAXN][MAXM];      
int U[MAXN][MAXM];      
char s[MAXN][MAXL];      
     
     void prefix(int p)      
     {      
       int i,k,L;      
             
       Prefix[0] = Prefix[1] = k = 0;      
       L = strlen(s[p]+1);      
             
       for (i = 2; i <= L; ++i)      
         {      
            while (k > 0 && s[p][i] != s[p][k+1])      
              k = Prefix[k];      
            if (s[p][i] == s[p][k+1])      
              k++;      
            Prefix[i] = k;      
         }      
     }      
           
     int KMP(int p,int r)      
     {      
        int L,l,i,k;      
              
        L = strlen(s[p]+1);      
        l = strlen(s[r]+1);      
              
        k = 0;      
        for (i = 1; i <= l; ++i)      
          {      
             while (k > 0 && s[p][k+1] != s[r][i])      
               k = Prefix[k];      
             if (s[p][k+1] == s[r][i])      
               k++;      
             if (k == L) return -1;      
          }      
        return k;      
     }      
     
     int main()
     {
	 freopen(FIN,"r",stdin);
	 freopen(FOUT,"w",stdout);

	 scanf("%d\n",&N);
	 for (i = 1; i <= N; ++i)
	   gets(s[i]+1);

	 for (i = 1; i <= N; ++i)
	   for (j = 1; j <= N; ++j)
	     if (i != j)
	       {
		  prefix(j);
		  C[i][j] = KMP(j,i);
		  if (C[i][j] == -1) mn|=(1<<(j-1));
	       }
	 maxq = 1 << N;
	 for (i = 1; i < maxq; ++i)
	   for (j = 1; j <= N; ++j)
	     if (!((1<<(j-1))&i))
	       {
		 D[j][i] = -1;
		 for (k = 1; k <= N; ++k)
		   if ((1<<(k-1))&i)
		     if (D[k][i-(1<<(k-1))]+C[j][k]>D[j][i])
		       {
			  D[j][i]=D[k][i-(1<<(k-1))]+C[j][k];
			  U[j][i]=k;
		       }
	       }

	 mx = -1; maxq -= 1+mn;
	 for (i = 1; i <= N; ++i)
	   if (D[i][maxq-(1<<(i-1))]>mx)
	     {
		mx = D[i][maxq-(1<<(i-1))];
		f = i;
	     }
	 printf("%s",s[f]+1);
	 maxq -= (1<<(f-1));
	 while (maxq > 0)
	   {
	      i = U[f][maxq];
	      mn = strlen(s[i]+1);
	      for (j = C[f][i]+1; j <= mn; ++j)
		printf("%c",s[i][j]);
	      maxq-=(1<<(i-1));
	      f = i;
	   }

	 return 0;
     }