Cod sursa(job #2113593)

Utilizator stelian2000Stelian Chichirim stelian2000 Data 24 ianuarie 2018 19:59:53
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.17 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

const int inf=1e9;

char sir[19][60010];
int cost[20][20],sol[20],d[(1<<18)+10][20],tata[(1<<18)+10][20],d1[60010],lung[20],v1[20],vaz[20],nod1[20],poz[20];
vector<pair<int,int>> v[20];

int solve(int a,int b)
{
    int l1=lung[a];
    int l2=lung[b];
    int l=min(l1,l2);
    for(int i=l1+1;i<=l1+l2;i++) sir[a][i]=sir[b][i-l1];
    int k=0;
    memset(d1,0,sizeof(d1));
    for(int i=2;i<=l1+l2;i++)
    {
        while(k!=0 && sir[a][i]!=sir[a][k+1]) k=d1[k];
        if(sir[a][i]==sir[a][k+1]) k++;
        d1[i]=k;
    }
    for(int i=l1+l2;i>=l1*2;i--) if(d1[i]==l1) {cost[a][b]=0;break;}
    k=l1+l2;
    while(1)
    {
        if(d1[k]<=l) return l1-d1[k];
        k=d1[k];
    }
}

int main()
{
    freopen("adn.in","r",stdin);
    freopen("adn.out","w",stdout);
    int n;
    scanf("%d\n",&n);
    for(int i=0;i<n;i++) {gets(sir[i]+1);lung[i]=strlen(sir[i]+1);}
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++) cost[i][j]=inf;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        if(i!=j)
        {
            int c=solve(j,i);
            cost[i][j]=min(cost[i][j],c);
        }
    for(int i=0;i<n;i++)
    if(vaz[i]==0)
    {
        int p=0,ll=0;
        for(int j=0;j<n;j++)
            if(i!=j && cost[i][j]==0)
            {
                if(lung[j]>lung[i]) {p=1;break;}
                else if(lung[j]==lung[i]) {v1[++ll]=j;}
            }
        if(p==1) {vaz[i]=1;continue;}
        for(int j=1;j<=ll;j++) vaz[v1[j]]=1;
    }
    int ll=0;
    for(int i=0;i<n;i++)
    if(vaz[i]==0) {poz[i]=ll;nod1[ll]=i;ll++;}
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            if(i!=j && vaz[i]==0 && vaz[j]==0) v[poz[i]].push_back({poz[j],cost[i][j]});
    n=ll;
    int lim=(1<<n);
    for(int mask=1;mask<lim;mask++)
        for(int i=0;i<n;i++)
            d[mask][i]=inf;
    for(int i=0;i<n;i++) {d[(1<<i)][i]=lung[nod1[i]];tata[(1<<i)][i]=-1;}
    for(int mask=1;mask<lim;mask++)
        for(int i=0;i<n;i++)
            if(mask&(1<<i))
                for(int j=0;j<v[i].size();j++)
                {
                    int vec=v[i][j].first,c=v[i][j].second;
                    if(mask&(1<<vec)) continue;
                    if(d[mask][i]+c<d[mask+(1<<vec)][vec])
                    {
                        d[mask+(1<<vec)][vec]=d[mask][i]+c;
                        tata[mask+(1<<vec)][vec]=i;
                    }
                }
    int ans=1e9,l=0;
    for(int i=0;i<n;i++) ans=min(ans,d[lim-1][i]);
    for(int i=0;i<n;i++)
        if(d[lim-1][i]==ans)
        {
            int nod=i,mask=lim-1;
            sol[++l]=nod1[nod];
            while(tata[mask][nod]!=-1)
            {
                int nod2=nod;
                nod=tata[mask][nod];
                sol[++l]=nod1[nod];
                mask-=(1<<nod2);
            }
            break;
        }
    int p=1;
    for(int i=l;i>=1;i--)
    {
        int l1=lung[sol[i]];
        for(int j=p;j<=l1;j++) printf("%c",sir[sol[i]][j]);
        p=lung[sol[i-1]]-cost[sol[i]][sol[i-1]]+1;
    }
    return 0;
}