Cod sursa(job #257)

Utilizator pauldbPaul-Dan Baltescu pauldb Data 8 decembrie 2006 11:53:09
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.91 kb
#include <stdio.h>
#include <string.h>

#define maxl 30010
#define maxn 19
#define maxx 40
#define maxm 262144
#define maxval 1000000000

char s[maxn][maxl];
int n,l,sol;
int a[maxn][maxx],b[maxn][maxx],p[maxn][maxx],grad[maxn],len[maxn];
int t[maxx];
int c[maxn][maxm],p1[maxn][maxm],p2[maxn][maxm];
int h[maxm],v[maxm];
char g[maxm],v2[maxm];

void prefix(int k)
{
     int i,x=-1;
     t[0]=-1;
     
     for (i=1;i<=len[k];i++)
     {
         while ((x>-1) && (s[k][x+1]!=s[k][i])) x=t[x];      
         
         if (s[k][x+1]==s[k][i]) x++;
         t[i]=x;
     }
}

int KMP(int j,int k)
{
    int i,x=-1;
    
    x=-1;
    for (i=0;i<=len[j];i++)
    {
        while ((x>-1) && (s[k][x+1]!=s[j][i])) x=t[x];
        
        if (s[k][x+1]==s[j][i]) x++;
    }
    
	return len[k]-x;
}

int fits(int j,int k)
{   
    int i,x=-1;
    
    x=-1;
    for (i=0;i<=len[j];i++)
    {
        while ((x>-1) && (s[k][x+1]!=s[j][i])) x=t[x];
        
        if (s[k][x+1]==s[j][i]) x++;
        if (x==len[k]) return 1;
    }
    
    return 0;
}

int count(int x)
{
    int rez=0;
    
    while (x>0)
    {
          rez=rez+x%2;
          x=x>>1;
    }
    
    return rez;
}

void arrange(int p,int r)
{
     int q=(p+r)/2,i=p,j=q+1,l=p-1;
     
     while ((i<=q) && (j<=r))
     {
           l++;
           if (g[i]<=g[j])
           {
                v[l]=h[i];
                v2[l]=g[i];
                i++;
           }
           else {
                    v[l]=h[j];
                    v2[l]=g[j];
                    j++;
                }
     }
     
     while (i<=q)
     {
           l++;
           v[l]=h[i];
           v2[l]=g[i];
           i++;
     }
     
     while (j<=r)
     {
           l++;
           v[l]=h[j];
           v2[l]=g[j];
           j++;
     }
     
     for (i=p;i<=r;i++) 
     {
         h[i]=v[i];
         g[i]=v2[i];
     }
}

void merge(int p,int r)
{
     if (p<r)
     {
             int q=(p+r)/2;
             merge(p,q);
             merge(q+1,r);
             arrange(p,r);
     }
}

int max(int x,int y)
{
    if (x>y) return x;
    return y;
}

void print(int x,int y)
{
     if (x==0) return;
     else {
			   int x2=p1[x][y],y2=p2[x][y];
               
               print(x2,y2);
               
               int i;
			   for (i=max(len[x]-(c[x][y]-c[x2][y2])+1,0);i<=len[x];i++) printf("%c",s[x][i]);
          }
}

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

	int i,j,k,x;
    
	scanf("%d ",&n);
    for (i=1;i<=n;i++) 
    {
        scanf("%s\n",&s[i]);
		len[i]=strlen(s[i])-1;
    }       
    
    for (i=1;i<=n;i++)
    {
        prefix(i);
        
        for (j=1;j<=n;j++) 
          if (i!=j)
          {
              grad[j]++;
			  a[j][grad[j]]=i;
              b[j][grad[j]]=KMP(j,i);
			  p[j][grad[j]]=i;
          }
          
        for (j=1;j<=n;j++)
		  if  ((i!=j) && (len[j]>=len[i]) && (fits(j,i)))
          {
              grad[j]++;
			  a[j][grad[j]]=i;
			  b[j][grad[j]]=0;
              p[j][grad[j]]=j;
		  }
	}

	l=(1<<n)-1;

	for (i=1;i<=l;i++)
	{
		h[i]=i;
		g[i]=count(i);
	}

	merge(1,l);

	for (i=1;i<=n;i++)
	  for (j=1;j<=l;j++) c[i][j]=maxval;

	for (i=0;i<=n;i++) c[i][0]=0;

	for (i=1;i<=n;i++) c[i][1<<(i-1)]=len[i]+1;

	for (i=1;i<=l;i++)
	  for (j=1;j<=n;j++)
		for (k=1;k<=grad[j];k++)
		  if (((h[i]&(1<<(a[j][k]-1)))==0) && (c[j][h[i]]+b[j][k]<c[p[j][k]][h[i]+(1<<(a[j][k]-1))]))
		  {
			 c[p[j][k]][h[i]+(1<<(a[j][k]-1))]=c[j][h[i]]+b[j][k];
			 p1[p[j][k]][h[i]+(1<<(a[j][k]-1))]=j;
			 p2[p[j][k]][h[i]+(1<<(a[j][k]-1))]=h[i];
		  }

	sol=maxval;

	for (i=1;i<=n;i++)
	  if (c[i][l]<sol)
	  {
		  sol=c[i][l];
		  x=i;
	  }
	  
//    printf("%d\n",sol);

	print(x,l);

    printf("\n");

    return 0;
}