Cod sursa(job #1143453)

Utilizator PatrikStepan Patrik Patrik Data 15 martie 2014 16:09:43
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.04 kb
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define NMAX 18
    #define LMAX 30005
    #define INF NMAX*LMAX
    char s[NMAX][LMAX] ;
    int N , pi[NMAX][LMAX] , sz[NMAX]  , c[NMAX][NMAX] , d[1<<NMAX][NMAX] , best;
    int urm[NMAX] , p[1<<NMAX][NMAX] , last , first;
    bool u[NMAX];

    void read();
    void solve();
    void write();
    void prefix();

    int main()
    {
        read();
        solve();
        write();
        return 0;
    }

    void read()
    {
        freopen("adn.in" , "r" , stdin );
        scanf("%d\n" , &N );
        for(int i = 0 ; i < N ; ++i )
        {
            scanf("%s" , s[i]+1);
            sz[i] = strlen(s[i]+1);
        }
    }

    void solve()
    {
        prefix();
        int k;
        for(int i = 0 ; i < N ; ++i )
            for(int j = 0 ; j < N ; ++j )
        {
            if(i == j) continue;
            k = 0;
            for(int p = 1 ; p <= sz[i] ; ++p )
            {
                while(k && s[i][p] != s[j][k+1])k = pi[j][k];
                if(s[i][p] == s[j][k+1])k++;
                if(k == sz[j])
                    u[j] = 1;
            }
            c[i][j] = k;
        }
        for(int i = 0 ; i < N ; ++i )
            if(!u[i])
            {
                d[1<<i][i] = sz[i];
                p[1<<i][i] = -1;
            }

        for(int i = 1 ; i < (1<<N) ; ++i )
        {
            for(int j = 0 ; j < N ; ++j )
                if(i&(1<<j) && !u[j])
                {
                    if(i!= 1<<j)d[i][j] = INF;
                    for(int k = 0 ; k < N ; ++k )
                        if(i&(1<<k) && k != j  && !u[k])
                        if (d[i^(1<<j)][k] + sz[j] - c[k][j] < d[i][j])
                        {
                            d[i][j] = d[i^(1<<j)][k] + sz[j] - c[k][j];
                            p[i][j] = k;
                        }
                }
        }
        int m = (1<<N)-1;
        for(int i  = 0 ; i < N ; ++i )
            if(u[i])m-=(1<<i);
        best = INF;
        for(int i = 0 ; i < N ; ++i )
            if(d[m][i] < best && !u[i])
            {
                best = d[m][i];
                last = i;
            }
        urm[last] = -1;
        for(;m;m-=1<<first)
        {
            first = last;
            urm[p[m][last]] = last;
            last = p[m][last];
        }
    }

    void prefix()
    {
        int k = 0;
        for(int i = 0 ; i < N ; ++i )
        {
            k = 0;
            for(int j = 2 ; j <= sz[i]  ; ++j )
            {
                while(k && s[i][j] != s[i][k+1])k = pi[i][k];
                if(s[i][j] == s[i][k+1])
                    pi[i][j] = ++k;
            }
        }
    }

    void write()
    {
        freopen("adn.out" , "w" , stdout );
        int x = first;
        printf("%s" , s[first]+1);
        while(urm[x] != -1)
        {
            printf("%s" , s[urm[x]]+c[x][urm[x]]+1);
            x = urm[x];
        }
    }