Cod sursa(job #178567)

Utilizator CezarMocanCezar Mocan CezarMocan Data 14 aprilie 2008 19:25:35
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.48 kb
#include <cstdio>
#include <string.h>
#define inf 2147483647   

using namespace std;

char v[20][30100];
long n,i,j,x[20][20],l[20],pi[30100],el[20],k,p,put[20],lr,lj,aux;
long t[20][1<<18],dui[20][1<<18],duj[20][1<<18],rez[20];

inline long min(long a, long b)
    {
    if (a<b)
        return a;
    else
        return b;    
    }

void prefix(long q)
    {
    long x,i,j;
    memset(pi,0,sizeof(pi));
    pi[0]=-1;
    pi[1]=0;
    for (i=2;i<=l[q];i++)
        {
        x=pi[i-1];
        if (v[q][x+1]==v[q][i])
            pi[i]=x+1;
        else
            {
            while (x>=0)
                {
                x=pi[x];
                if (x<0)
                    break;
                if (v[q][x+1]==v[q][i])
                    {
                    pi[i]=x+1;
                    break;    
                    }    
                }
            }
        }    
    }

long KMP(long p, long q)
    {
    prefix(q);  
    long x,i,j;
    x=0;
    for (i=1;i<=l[p];i++)
        {
        if (v[p][i]==v[q][x+1])
            x++;
        else
            {
            while (x>=0)
                {
                x=pi[x];
                if (x<0)
                    break;    
                if (v[p][i]==v[q][x+1])
                    {
                    x++;
                    break;    
                    }
                }    
            }    
        if (x<0)
            x=0;
        if (x==l[q])
            return x;
        }
    return x;
    }

int main(){
freopen("adn.in","r",stdin);
freopen("adn.out","w",stdout);    
scanf("%d",&n);
for (i=0;i<=20;i++)
    put[i]=1<<i;
for (i=1;i<=n;i++)
    {
    scanf("%s",v[i]);
    l[i]=strlen(v[i]);
    for (j=l[i];j>=1;j--)
        v[i][j]=v[i][j-1];
    }
for (i=1;i<=n;i++)
    for (j=1;j<=n;j++)
        if (i!=j)
            {
            x[i][j]=KMP(i,j);
/*            if (x[i][j]==l[i])
                el[i]=1;
            if (x[i][j]==l[j])
                el[j]=1;*/
            }
for (i=n;i>=1;i--)
    if (el[i]==1)
        {
        n--;
        for (j=i;j<=n;j++)
            for (k=1;k<=30000;k++)
                v[j][k]=v[j+1][k];
        }   
/*for (i=1;i<=n;i++)
    {
    for (j=1;j<=n;j++)
        printf("%d ",x[i][j]);
    printf("\n");
    }   */
//dinamica pe configuratii in 2^n*n^2
//t[i][j]=costul minim daca ultimu pus este i si am configuratia j
for (i=0;i<=put[n];i++)
    for (j=0;j<=n;j++)
        t[j][i]=inf;
for (i=1;i<=n;i++)
    t[i][put[i-1]]=l[i];
for (j=1;j<=put[n];++j)
    {
    for (i=1;i<=n;i++)
        //verific daca am i-ul in configuratia curenta
        if (put[i-1]&j)
            for (k=1;k<=n;k++)
                if (!(put[k-1]&j))
                    {
                    if ((t[i][j]+l[k]-x[i][k])<t[k][j|put[k-1]])
                        {
                        t[k][j|put[k-1]]=t[i][j]+l[k]-x[i][k];
                        dui[k][j|put[k-1]]=i;
                        duj[k][j|put[k-1]]=j;
                        }
                    }
    }
lr=1;
for (i=2;i<=n;i++)
    if (t[i][(put[n])-1]<t[lr][put[n]-1])  
        lr=i;
i=0;
lj=put[n]-1;
while (lr!=0)
    {
    i++;
    rez[i]=lr;
    aux=lr;
    lr=dui[aux][lj];
    lj=duj[aux][lj]; 
    }
for (j=1;j<=l[rez[n]];j++)
    printf("%c",v[rez[n]][j]);
for (i=n;i>1;i--)
    {
    for (j=x[rez[i]][rez[i-1]]+1;j<=l[rez[i-1]];j++)
        printf("%c",v[rez[i-1]][j]);    
    }
return 0;
}