Cod sursa(job #1726758)

Utilizator Alexa2001Alexa Tudose Alexa2001 Data 8 iulie 2016 22:32:26
Problema ADN Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.34 kb
#include <algorithm>
#include <fstream>
#include <vector>
#include <cstring>

using namespace std;

ifstream f("adn.in");
ofstream g("adn.out");

const int NM = 30005;

int Ans, ans, i, N, n, m, interzis=0, pi[NM], sz[21], j, x[21][21], mask, A, B;
int dp[(1<<18)+3][21], r[(1<<18)+3][21];

char a[21][NM], ch[21*NM];
bool Ok;
vector<int> v1, v2;

void Kmp(char a[], int n)
{
    int i, k=0;
    pi[1]=0;

    for(i=2; i<=n; ++i)
    {
        while(k && a[k+1]!=a[i])
            k=pi[k];

        if(a[k+1]==a[i]) ++k;
        pi[i]=k;
    }
}

int kmp(char a[], char b[], int n, int m)
{
    int i, k=0;
    for(i=1; i<=m; ++i)
    {
        while(k && a[k+1]!=b[i])
            k=pi[k];

        if(a[k+1]==b[i]) ++k;
        if(k==n && n!=m) Ok=0;
    }
    return k;
}

int main()
{
    f>>n;
    for(i=0; i<n; ++i)
    {
        f>>(a[i]+1);
        sz[i] = strlen(a[i]+1);
    }

    for(i=0; i<n; ++i)
    {
         Ok=1;

         Kmp(a[i], sz[i]);

         for(j=0; j<n; ++j)
         if(i!=j)
            x[j][i] = kmp(a[i], a[j], sz[i], sz[j]); /// a[i] - prefix
                                       /// a[j] - sufix

         if(!Ok) interzis += (1<<i);
         else Ans += sz[i];

         r[1<<i][i] = n;
    }

    for(mask=1; mask<(1<<n); ++mask)
    if(!(mask&interzis))
    {
         v1.clear();
         v2.clear();

         for(i=0; i<n; ++i)
         if(!((1<<i)& interzis))
         {
             if(mask& (1<<i)) v1.push_back(i);
             else v2.push_back(i);
         }

         for(i=0; i<v1.size(); ++i)
            for(j=0; j<v2.size(); ++j)
            {
                A = v1[i];
                B = v2[j];
                if( dp[mask^(1<<B)][B] < dp[mask][A] + x[A][B] )
                {
                    dp[mask^(1<<B)][B] = dp[mask][A] + x[A][B];
                    r[mask^(1<<B)][B] = A;
                }
            }
    }

    mask = (mask-1)^interzis;

    for(i=0; i<n; ++i)
    if( !(interzis &(1<<i)) && ans < dp[mask][i])
    {
        ans = dp[mask][i];
        A = i;
    }

    int ind = Ans - ans;

    while(mask)
    {
        for(i=sz[A]; i > x[ r[mask][A] ][A]; --i)
            ch[ind--] = a[A][i];

        mask -= (1<<A);
        A = r[mask+(1<<A)][A];
    }

    g<<(ch+1)<<'\n';

    return 0;
}