Cod sursa(job #1586607)

Utilizator SilviuIIon Silviu SilviuI Data 1 februarie 2016 14:38:29
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.22 kb
#include <stdio.h>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#define lmax 30010
#define inf 80000

using namespace std;

int n,startp,nr;
int dp[20][lmax*10],path[20][lmax*10];
int urm[lmax],dif[20][20],sol[20];
bool viz[20][lmax*10];
char ss[lmax];
bool fr[20];
string s[20];
vector < pair< int,int > > g[20];

int memo(int nod,int mask)
{
    if (mask==0) return 0;
    if (viz[nod][mask]) return dp[nod][mask];
    viz[nod][mask]=true;
    for (unsigned int i=0;i<g[nod].size();i++) {
        int y=g[nod][i].first-1;
        if (y+1==startp && mask!=1<<y) continue;
        if (((mask>>y)&1)==1) {
            int val=memo(y+1,mask-(1<<y));
            if (dp[nod][mask]>val) {
                path[nod][mask]=y+1; dp[nod][mask]=val;
            }
        }
    }
    return dp[nod][mask];
}

bool nrbit(int x)
{
    return (x&(x-1));
}

void findpath(int x,int mask)
{
    if (nrbit(mask)==0) return; else
    {
        int y=path[x][mask];
        nr++; sol[nr]=y;
        findpath(y,mask-(1<<(y-1)));
    }
}

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

    scanf("%d ",&n);
    for (int i=1;i<=n;i++) {
        gets(ss); s[i]=ss; s[i].insert(0," ");
    }

    for (int i=1;i<=n;i++) {
        if (fr[i]) continue;
        for (int j=1;j<=n;j++)
            if (i!=j && s[i].size()>=s[j].size() && fr[j]==false) {
                urm[1]=0; int k=0;
                for (int l=2;l<=(int)s[j].size()-1;l++) {
                    while (k>0 && s[j][l]!=s[j][k+1]) k=urm[k];
                    if (s[j][l]==s[j][k+1]) k++;
                    urm[l]=k;
                }

                bool ok=false; k=0;
                for (int l=1;l<=(int)s[i].size()-1;l++) {
                    while (k>0 && s[i][l]!=s[j][k+1]) k=urm[k];
                    if (s[i][l]==s[j][k+1]) k++;
                    if (k==s[j].size()-1) { ok=true; break; }
                }

                if (ok) fr[j]=true;
        }
    }

    for (int i=1;i<=n;i++)
        if (!fr[i]) {
            for (int j=1;j<=n;j++)
                if (i!=j && !fr[j]) {
                    urm[1]=0; int k=0;
                    for (int l=2;l<=(int)s[j].size()-1;l++) {
                        while (k>0 && s[j][l]!=s[j][k+1]) k=urm[k];
                        if (s[j][l]==s[j][k+1]) k++;
                        urm[l]=k;
                    }

                    k=0;
                    for (int l=1;l<=(int)s[i].size()-1;l++) {
                        while (k>0 && s[i][l]!=s[j][k+1]) k=urm[k];
                        if (s[i][l]==s[j][k+1]) k++;
                        if (k==s[j].size()-1) k=urm[k];
                    }

                    g[i].push_back(make_pair(j,s[j].size()-k));  dif[i][j]=k;
                }
    }

    int maxx=(1<<n)-1,best=2e9,nrnod=0;

    for (int i=1;i<=n;i++)
        if (fr[i]) maxx=maxx-(1<<(i-1));

    for (startp=1;startp<=n;startp++)
    if (!fr[startp])
    {
        for (int i=1;i<=n;i++)
            for (int k=1;k<=maxx;k++)
                dp[i][k]=2e9,viz[i][k]=false,path[i][k]=0;

        for (unsigned int i=0;i<g[startp].size();i++) {
            int val=memo(g[startp][i].first,maxx-(1<<(g[startp][i].first-1)))+g[startp][i].second;
            if (dp[startp][maxx]>val) {
               path[startp][maxx]=g[startp][i].first; dp[startp][maxx]=val;
            }
        }

        if (dp[startp][maxx]<best) { best=dp[startp][maxx]; nrnod=startp; }
    }

    startp=nrnod;
    for (int i=1;i<=n;i++)
        for (int k=1;k<=maxx;k++)
            dp[i][k]=2e9,viz[i][k]=false,path[i][k]=0;

    for (unsigned int i=0;i<g[startp].size();i++) {
        int val=memo(g[startp][i].first,maxx-(1<<(g[startp][i].first-1)))+g[startp][i].second;
        if (dp[startp][maxx]>val) {
            path[startp][maxx]=g[startp][i].first; dp[startp][maxx]=val;
        }
    }

    for (int i=1;i<=n;i++) s[i].erase(s[i].begin());

    nr=1; sol[1]=startp; findpath(startp,maxx);

    for (int i=1;i<nr;i++) {
        int l=dif[sol[i]][sol[i+1]];
        for (int j=0;j<(int)s[sol[i]].size()-l;j++) printf("%c",s[sol[i]][j]);
    }

    cout<<s[sol[nr]]<<'\n';

    return 0;
}