Cod sursa(job #1803746)

Utilizator bogdan10bosBogdan Sitaru bogdan10bos Data 11 noiembrie 2016 19:20:25
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.28 kb
#include <bits/stdc++.h>

using namespace std;

#define FILE_IO

typedef pair<int, int> pii;

int mod[] = {(int)1e9 + 7, (int) 1e9 + 9};
int base[] = {7, 5};

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 hsh[20][30005][2];

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;
}

pii HASH(int id, int st, int dr)
{
    int h[2];
    for(int k = 0; k <= 1; k++)
        h[k] = (hsh[id][dr][k] - (1LL * hsh[id][st - 1][k] * p[dr - st + 1][k]) % mod[k] + mod[k]) % mod[k];
    return {h[0], h[1]};
}

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 j = 1; j <= l[i]; j++)
        {
            int x = getval(s[i][j]);
            for(int k = 0; k <= 1; k++)
                hsh[i][j][k] = ( (1LL * hsh[i][j - 1][k] * base[k]) % mod[k] + x ) % mod[k];
        }
    }

    for(int k = 0; k <= 1; k++)
    {
        p[0][k] = 1;
        for(int i = 1; i <= 30000; i++)
            p[i][k] = (1LL * p[i - 1][k] * base[k]) % mod[k];
    }

    for(int i = 0; i < N; i++)
        f[i] = 1;
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < N; j++)
        {
            if(i == j)  continue;
            if(l[j] < l[i]) continue;
            for(int k = 1; k + l[i] - 1 <= l[j]; k++)
                if( HASH(i, 1, l[i]) == HASH(j, k, k + l[i] - 1) )
                {
                    f[i] = 0;
                    break;
                }
            if(!f[i])   break;
        }
    }
    for(int i = 0; i < N; i++)
        if(f[i])
            need[M++] = i;

    for(int i = 0; i < N; i++)
    {
        if(!f[i])   continue;
        for(int j = 0; j < N; j++)
        {
            if(!f[j])   continue;
            if(i == j)
            {
                cmn[i][j] = l[i];
                continue;
            }
            cmn[i][j] = 0;
            for(int k = min(l[i], l[j]); k >= 1; k--)
            {
                pii h1 = HASH(i, l[i] - k + 1, l[i]);
                pii h2 = HASH(j, 1, k);
                if( h1 == h2 )
                {
                    cmn[i][j] = k;
                    break;
                }
            }
        }
    }

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

    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;
}