Cod sursa(job #545175)

Utilizator S7012MYPetru Trimbitas S7012MY Data 2 martie 2011 20:41:36
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.97 kb
#include <cstdio>
#include <cstring>
#define deb(n) fprintf(stderr,"%d ",(n));
#define debnl fprintf(stderr,"\n");
#define DN 20
#define DX 1<<19
#define DL 300005
#define MULT 0x3f3f3f3f

int n,cost[DN][DN],lg[DN],pi[DL],newn[DN],m,
    dp[DX][DN],pre[DX][DN];
char seq[DN][DL];

void cp(int x) {
    for(int k=0,i=2; i<=lg[x]; ++i) {
        for(;k && seq[x][k+1]!=seq[x][i];k=pi[k]);
        if(seq[x][k+1]==seq[x][i]) ++k;
        pi[i]=k;
    }
}

int kmp(int x, int y, int &cost) {
    int ret=0;
    for(int k=0,i=1;i<=lg[y]; ++i) {
        for(;k && seq[x][k+1]!=seq[y][i];k=pi[k]);
        if(seq[x][k+1]==seq[y][i]) ++k;
        if(k==lg[x]) ret=1;
        cost=k;
    }
    return ret;
}

int viz[DN];

void afis(int x,int y) {
    if(0==y) return;
    afis(pre[y][x],y^(1<<(x-1)));
    for(int i=cost[newn[pre[y][x]]][newn[x]]+1;i<=lg[newn[x]]; ++i) printf("%c",seq[newn[x]][i]);
}

int main()
{
    freopen("adn.in","r",stdin);
    freopen("adn.out","w",stdout);
    scanf("%d",&n);
    for(int i=1; i<=n; ++i) {
        scanf("%s",seq[i]+1);
        lg[i]=strlen(seq[i]+1);
    }
    for(int i=1; i<=n; ++i) {
        cp(i);
        for(int j=1; j<=n; ++j) if(i!=j) {
           // cp(i);
            int cst=0;
            if(kmp(i,j,cst)) viz[i]=1;
            //deb(cst)
            cost[j][i]=cst;
        }
    }
    for(int i=1; i<=n; ++i) if(0==viz[i]) newn[++m]=i;
    //hamilton
    memset(dp,MULT,sizeof(dp));
    for(int i=1; i<=m; ++i) dp[1<<(i-1)][i]=lg[newn[i]];
    for(int i=0; i<(1<<m); ++i) for(int j=1;j<=m; ++j) if(i&(1<<(j-1)))
        for(int k=1; k<=m; ++k) if(0==(i&(1<<(k-1)))) if(dp[i^(1<<(k-1))][k]>dp[i][j]+lg[newn[k]]-cost[newn[j]][newn[k]]) {
            dp[i^(1<<(k-1))][k]=dp[i][j]+lg[newn[k]]-cost[newn[j]][newn[k]];
            pre[i^(1<<(k-1))][k]=j;
        }
    //deb(dp[(1<<m)-1][3])
    int rez=MULT,start;
    for(int i=1; i<=m; ++i) if(dp[(1<<m)-1][i]<rez) {
        rez=dp[(1<<m)-1][i];
        start=i;
    }
    afis(start,(1<<m)-1);
    return 0;
}