Cod sursa(job #1197901)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 14 iunie 2014 01:00:14
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.84 kb
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

#define Nmax 30005
#define inf 50000
#define INF 0x3f3f3f3f

using namespace std;
char S[20][Nmax],sol[20][Nmax];
int cost[20][20],nrs;
int DP[20][(1<<19)+666];
int daddy[20][(1<<19)+666];

int KMP_distance(char A[Nmax],char B[Nmax])
{
    int i,q,N,M;
    N = strlen(A) - 1;
    M = strlen(B) - 1;
    vector<int> P;
    for(int i = 0; i < M + 5; ++i)
        P.push_back(0);

    q = 0;
    for(i = 2; i <= M; ++i)
    {
        while(q && B[i] != B[q + 1])
            q = P[q];
        q += (B[i] == B[q+1]);
        P[i] = q;
    }
    q = 0;
    for(i = 1; i <= N; ++i)
    {
        while(q && A[i] != B[q+1])
            q = P[q];
        q += (A[i] == B[q+1]);
        if(q == M)
            return -666;/// :D
    }
    return q;
}

void read()
{
    scanf("%d",&nrs);
    for(int i = 1; i <= nrs; ++i){
        scanf("%s",S[i] + 1);
        S[i][0] = '#';
    }
    for(int i = 1; i <= nrs; ++i)
        for(int j = 1; j <= nrs; ++j)
            if(i != j)
            {
                if(KMP_distance(S[i],S[j]) == -666)
                {
                    for(int k = j; k < nrs; ++k)
                        strcpy(S[k],S[k+1]);
                    --nrs;
                    i-=2;
                    j = nrs + 1;
                }
            }
}

void build()
{
    for(int i = 0; i < nrs; ++i)
        for(int j = 0; j < nrs; ++j)
            if( i != j )
                cost[i][j] = KMP_distance(S[i+1],S[j+1]);
}

void dynamic()
{
    memset(DP,-1,sizeof(DP));
    for(int i = 0; i < nrs; ++i)
        DP[i][1<<i] = 0;
    for(int mask = 0; mask < (1<<nrs); ++ mask)
        for(int i = 0; i < nrs; ++i)
            if( mask & (1 << i))
                for(int j = 0; j < nrs; ++j)
                    if( i != j && (mask & (1 << j)) )
                        if(DP[i][mask] < DP[j][mask^(1<<i)] + cost[j][i]){
                            DP[i][mask] = DP[j][mask^(1<<i)] + cost[j][i];
                            daddy[i][mask] = j;
                        }
}

void print()
{
    int mask = ((1<<nrs) - 1),nodc,best = -1,besti,aux,D;
    for(int i = 0; i < nrs; ++i)
        if(DP[i][mask] > best){
            best = DP[i][mask];
            besti = i;
        }
    for(int i = 1; i <= nrs; ++i)
    {
        strcpy(sol[nrs-i+1],S[besti + 1]);
        aux = mask ^ (1<<besti);
        besti = daddy[besti][mask];
        mask = aux;
    }
    for(int i = 1; i < nrs; ++i){
        D = KMP_distance(sol[i],sol[i+1]);
        sol[i][strlen(sol[i]) - D ] = 0;
        printf("%s",sol[i]+1);
    }
    printf("%s",sol[nrs]+1);
}

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

    read();
    build();
    dynamic();
    print();

    return 0;
}