Cod sursa(job #1293150)

Utilizator atatomirTatomir Alex atatomir Data 15 decembrie 2014 14:53:26
Problema ADN Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.74 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;

#define maxN 20
#define maxL 30011
#define maxLog (1<<18)
#define c second
#define d first
#define INF 1000000000

long n,i,q,j,conf,act,mask;
char str[maxN][maxL];
long pr[maxN][maxL],len[maxN];
vector<pair<long,long> > list[maxN];

long dp[maxN][maxLog];
long prov[maxN][maxLog];

long Sol,pSol,nSol;

long KMP(long a,long b){
    long i,q;
    long pref[maxL];

    pref[1] = 0; q = 0;
    for(i=1;i<=len[a];i++){
        while(q && str[a][i] != str[b][q+1]) q = pr[b][q];
        if(str[a][i] == str[b][q+1]) q++;
        pref[i] = q;
        if(q == len[b]) {
            mask &= ((1<<n)-1) ^ (1<<(b-1));
            return 0;
        }
    }
    return len[b] - pref[len[a]];
}

long Calc(long nod,long conf){
    if(dp[nod][conf] == -1){
        dp[nod][conf] = INF;
        for(long i=0;i<list[nod].size();i++){
            long newNod = list[nod][i].d;
            if(conf & 1<<(newNod-1)){
                long newConf = conf ^ (1 << (nod-1));
                if(dp[nod][conf] > Calc(newNod,newConf) + list[nod][i].c){
                    dp[nod][conf] = Calc(newNod,newConf) + list[nod][i].c;
                    prov[nod][conf] = i;
                }
            }
        }
    }
    return dp[nod][conf];
}

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

    scanf("%ld",&n);
    for(i=1;i<=n;i++){
        scanf("%s",str[i]+1);

        q=0; len[i] = strlen(str[i]+1);
        for(j=2;j<=len[i];j++){
            while(q && str[i][j] != str[i][q+1]) q = pr[i][q];
            if(str[i][j] == str[i][q+1]) q++;
            pr[i][j] = q;
        }
    }

    mask = (1 << n)-1;

    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            if(i==j) continue;

            long size = KMP(i,j);
            list[i].push_back(make_pair(j,size));
        }
    }

    memset(dp,-1,sizeof(dp));
    for(i=1;i<=n;i++) {
        dp[i][1<<(i-1)] = 0;
        prov[i][1<<(i-1)] = 0;
    }

    Sol = INF;
    for(i=1;i<=n;i++){
        for(j=0;j<list[i].size();j++){
            if(Sol > len[i] + Calc(list[i][j].d,mask)){
                Sol = len[i] + Calc(list[i][j].d,mask);
                pSol = j; nSol = i;
            }
        }
    }

    act = list[nSol][pSol].d;
    for(i=1;i<=len[act];i++) printf("%c",str[act][i]);

    conf = (1<<n)-1;
    while(conf){
        long newNod = list[act][prov[act][conf]].d;
        long need   = list[act][prov[act][conf]].c;

        conf ^= 1 <<(act-1);
        if(conf)
        for(i=len[newNod]-need+1;i<=len[newNod];i++) printf("%c",str[newNod][i]);
        act = newNod;
    }


    return 0;
}