Cod sursa(job #612938)

Utilizator GavrilaVladGavrila Vlad GavrilaVlad Data 13 septembrie 2011 17:42:08
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.33 kb
#include <cstdio>
#include <cstring>

using namespace std;

#define maxl 30010
#define maxn 20
#define inf 2000000000

int n, i, j, k, st, t, pr, poz;
int pi[maxl], conf[maxn], l[maxn];
char s[maxn][maxl];
int d[1<<18][maxn], rec[1<<18][maxn], v[maxn][maxn];
char sol[maxn*maxl];

void kmp()
{
    for(int i=1; i<=n; ++i)
    {
        k=0;
        for(int j=2; j<=l[i]; ++j)
        {
            while(s[i][k+1]!=s[i][j] && k>0)
                k=pi[k];
            if(s[i][k+1]==s[i][j])
                pi[j]=++k;
            else
                pi[j]=0;
        }

        for(int j=1; j<=n; ++j)
        {
            if(j==i)
                continue;
            k=0;
            for(int p=1; p<=l[j]; ++p)
            {
                while(s[i][k+1]!=s[j][p] && k>0)
                    k=pi[k];
                if(s[i][k+1]==s[j][p])
                    ++k;

                if(k==l[i] && p<l[j])
                {
                    st=st|(1<<(i-1));
                    k=0;
                    break;
                }
            }

            v[j][i]=k;
        }
    }
}

void dinamica()
{
    for(int i=0; i<(1<<n); ++i)
        for(int j=0; j<=n; ++j)
            d[i][j]=inf;

    d[st][0]=0;

    for(int i=0; i<(1<<n); ++i)
    {
        for(int j=0; j<n; ++j)
            conf[j+1]=((i>>j)&1);

        for(int j=0; j<=n; ++j)
        {
            for(int k=1; k<=n; ++k)
            {
                if(conf[k])
                    continue;
                if(d[i][j]+l[k]-v[j][k]<d[i|(1<<(k-1))][k])
                {
                    d[i|(1<<(k-1))][k]=d[i][j]+l[k]-v[j][k];
                    rec[i|(1<<(k-1))][k]=j;
                }
            }
        }
    }
}

void reconstituire()
{
    poz=1;
    for(int i=1; i<=n; ++i)
        if(d[(1<<n)-1][i]<d[(1<<n)-1][poz])
            poz=i;

    int x=(1<<n)-1;

    while(x!=st)
    {
        int np=rec[x][poz];

        for(int i=l[poz]; i>v[np][poz]; --i)
            sol[++t]=s[poz][i];

        x-=(1<<(poz-1));
        poz=np;
    }
}

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

    scanf("%d\n", &n);
    for(int i=1; i<=n; ++i)
    {
        scanf("%s", s[i]+1);
        l[i]=strlen(s[i]+1);
    }

    kmp();
    dinamica();
    reconstituire();

    for(int i=t; i; --i)
        printf("%c", sol[i]);
    printf("\n");

    return 0;
}