Cod sursa(job #1804687)

Utilizator bogdan10bosBogdan Sitaru bogdan10bos Data 12 noiembrie 2016 21:26:14
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.2 kb
#include <bits/stdc++.h>

using namespace std;

#define FILE_IO

typedef pair<int, int> pii;

int N, B;
int b[20];
char s[20][30005];
int cmn[20][20];
int dp[270005][20];
int lst[270005][20];
int lg2[270005];
int p[270005][2];
int l[20];
vector <int> ord;

int M;
int f[20];
int need[20];

int phi[30005];

int getval(char ch)
{
    if(ch == 'A')   return 1;
    if(ch == 'G')   return 2;
    if(ch == 'C')   return 3;
    if(ch == 'T')   return 4;
    return 0;
}

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

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

    for(int i = 0; i < N; i++)
        f[i] = 1;

    for(int i = 0; i < N; i++)
    {
        int k = 0;
        for(int j = 2; j <= l[i]; j++)
        {
            while(k > 0 && s[i][j] != s[i][k + 1])
                k = phi[k];
            if(s[i][j] == s[i][k + 1]) k++;
            phi[j] = k;
        }

        for(int j = 0; j < N; j++)
        {
            if(i == j)  continue;
            int k = 0;
            for(int p = 1; p <= l[j]; p++)
            {
                while(k > 0 && s[j][p] != s[i][k + 1])
                    k = phi[k];
                if(s[j][p] == s[i][k + 1])  k++;
                if(k == l[i])   f[i] = 0;
            }
            cmn[j][i] = k;
        }
    }

    for(int i = 0; i < N; i++)
        if(f[i])
            need[M++] = i;

    for(int i = 2; i <= 1 << M; i++)
    {
        lg2[i] = lg2[i - 1];
        if( (2 << lg2[i]) == i )
            lg2[i]++;
    }

    for(int msk = 1; msk < 1 << M; msk++)
    {
        if( !(msk & (msk - 1)) )
        {
            dp[msk][ lg2[msk] ] = l[ need[ lg2[msk] ] ];
            lst[msk][ lg2[msk] ] = 0;
            continue;
        }

        int aux = msk;
        B = 0;
        while(aux)
        {
            b[ ++B ] = lg2[aux];
            aux -= 1 << lg2[aux];
        }

        for(int ii = 1, i = b[ii]; ii <= B; ii++, i = b[ii])
        {
            dp[msk][i] = 1 << 30;
            for(int jj = 1, j = b[jj]; jj <= B; jj++, j = b[jj])
            {
                if(ii == jj)    continue;
                if(dp[msk][i] > dp[msk ^ (1 << i)][j] + l[ need[i] ] - cmn[ need[j] ][ need[i] ])
                {
                    dp[msk][i] = dp[msk ^ (1 << i)][j] + l[ need[i] ] - cmn[ need[j] ][ need[i] ];
                    lst[msk][i] = j;
                }
            }
        }
    }

    int ans = 1 << 30;
    int id = -1;
    int msk = (1 << M) - 1;
    for(int i = 0; i < M; i++)
        if(dp[msk][i] < ans)
        {
            ans = dp[msk][i];
            id = i;
        }

    while(msk)
    {
        ord.push_back(need[id]);
        int newid = lst[msk][id];
        msk ^= 1 << id;
        id = newid;
    }

    reverse(ord.begin(), ord.end());
    printf("%s", s[ ord[0] ] + 1);
    for(int i = 1; i < ord.size(); i++)
    {
        for(int j = 1 + cmn[ ord[i - 1] ][ ord[i] ]; j <= l[ ord[i] ]; j++)
            printf("%c", s[ ord[i] ][j]);
    }
    printf("\n");

    return 0;
}