Cod sursa(job #1805917)

Utilizator LucianTLucian Trepteanu LucianT Data 14 noiembrie 2016 17:44:54
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.73 kb
#include <bits/stdc++.h>
#define maxN 18
#define maxL 30003
#define INF (1<<30)
using namespace std;
bool seen[maxN+1];
int solution[maxN+1];
int pi[maxN+1][maxL];
char str[maxN+1][maxL];
int n,m,i,j,x,mask,cst,sol=INF,last;
int len[maxN+1],cost[maxN+1][maxN+1],used[maxN+1];
int dp[1<<maxN][maxN+1],t[1<<maxN][maxN+1];
inline bool powerOf2(int x)
{
    return !(x&(x-1));
}
void buildPrefix(int index)
{
    int k=0;
    for(int i=2;i<=len[index];i++)
    {
        while(k>0 && str[index][i]!=str[index][k+1])
            k=pi[index][k];
        if(str[index][i]==str[index][k+1])
            k++;
        pi[index][i]=k;
    }
}
void matchStrings(int i,int j)
{
    int k=0;
    for(int pos=1;pos<=len[i];pos++)
    {
        while(k>0 && str[i][pos]!=str[j][k+1])
            k=pi[j][k];
        if(str[i][pos]==str[j][k+1])
            k++;
        if(k==len[j])
        {
            cost[i][j]=0;
            seen[j]=true;
            break;
        }
    }
    if(cost[i][j]==-1)
        cost[i][j]=len[j]-k;
}
int main()
{
    freopen("adn.in","r",stdin);
    freopen("adn.out","w",stdout);
    scanf("%d\n",&n);
    for(i=1;i<=n;i++)
        scanf("%s\n",str[i]+1),
        len[i]=strlen(str[i]+1),
        buildPrefix(i);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        {
            if(i==j)
                continue;
            cost[i][j]=-1;
            matchStrings(i,j);
        }
    for(i=1;i<=n;i++)
        if(!seen[i])
            used[++m]=i;
    for(i=1;i<=m;i++)
        dp[1<<(i-1)][i]=len[used[i]],
        t[1<<(i-1)][i]=-1;
    for(mask=1;mask<(1<<m);mask++)
    {
        if(powerOf2(mask))
            continue;
        for(i=1;i<=m;i++)
        {
            if(!(mask&(1<<(i-1))))
                continue;
            dp[mask][i]=INF;
            t[mask][i]=-1;
            for(j=1;j<=m;j++)
            {
                if(i==j)
                    continue;
                if(!(mask&(1<<(j-1))))
                    continue;
                int newval=dp[mask^(1<<(i-1))][j]+cost[used[j]][used[i]];
                if(newval<dp[mask][i])
                    dp[mask][i]=newval,
                    t[mask][i]=j;
            }
        }
    }
    sol=INF;
    for(i=1;i<=m;i++)
        if(dp[(1<<m)-1][i]<sol)
            sol=dp[(1<<m)-1][i],
            last=i;
    mask=(1<<m)-1;
    while(last!=-1)
    {
        solution[++x]=used[last];
        int aux=last;
        last=t[mask][last];
        mask^=(1<<(aux-1));
    }
    printf("%s",str[solution[x]]+1);
    for(i=x-1;i;i--)
        for(j=len[solution[i]]-cost[solution[i+1]][solution[i]]+1;str[solution[i]][j];j++)
            printf("%c",str[solution[i]][j]);
    return 0;
}