Cod sursa(job #1008801)

Utilizator assa98Andrei Stanciu assa98 Data 11 octombrie 2013 21:00:24
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.39 kb
#include <cstdio>
#include <cstring>
using namespace std;

const int MAX_N=18;
const int MAX_L=30100;
const int INF=1000000;

int from[300000][MAX_N];

int d[300000][MAX_N];
int c[MAX_N][MAX_N];

char a[MAX_N][MAX_L];
int pi[MAX_N][MAX_L];
int sz[MAX_N];

void prefix(const char s[MAX_L],int pi[MAX_L],int n) {
    pi[1]=0;
    int p=0;
    for(int i=2;i<=n;i++) {
        while(p&&s[i]!=s[p+1]) {
            p=pi[p];
        }
        if(s[i]==s[p+1]) {
            p++;
        }
        pi[i]=p;
    }
}



int kmp(int x,int y) {

    int p=0;
    for(int i=1;i<=sz[x];i++) { //cel mai lung prefix din y al sirului x[1..i]
        while(p&&a[x][i]!=a[y][p+1]) {
            p=pi[y][p];
        }
        if(a[x][i]==a[y][p+1]) {
            p++;
        }
        if(p==sz[y]) {
            return p;
        }
    }
    return p;
}

void afisare(int m,int p) {
    fprintf(stderr,"%d %d\n",p,m);
    int nm=m-(1<<p);
    if(from[m][p]==-1) {
        printf("%s",a[p]+1);
        return;
    }
    afisare(nm,from[m][p]);
    for(int i=c[from[m][p]][p]+1;i<=sz[p];i++) {
        printf("%c",a[p][i]);
    }

}


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

    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++) {
        scanf(" %s ",a[i]+1);
        sz[i]=strlen(a[i]+1);
        prefix(a[i],pi[i],sz[i]);
    }

    for(int i=0;i<n;i++) {
        for(int j=0;j<n;j++) {
            c[i][j]=kmp(i,j);
        }
    }

    for(int i=0;i<(1<<n);i++) {
        for(int j=0;j<n;j++) {
            d[i][j]=INF;
            from[i][j]=-1;
        }
    }

    for(int i=0;i<n;i++) {
        d[(1<<i)][i]=sz[i];
        from[(1<<i)][i]=-1;
    }

    for(int i=1;i<(1<<n);i++) {
        for(int j=0;j<n;j++) {
            if(d[i][j]!=INF) {
                continue;
            }
            if(i&(1<<j)) {

                for(int b=0;b<n;b++) {
                    if( b!=j &&(i&(1<<b)) ) {
                        int ni=i^(1<<j);
                        int cst=d[ni][b]+sz[j]-c[b][j];
                        if(cst<d[i][j]) {
                            d[i][j]=cst;
                            from[i][j]=b;
                        }
                    }

                }
            }
        }
    }

    int ans=INF;
    int poz;
    for(int i=0;i<n;i++) {
        if(d[(1<<n)-1][i]<ans) {
            ans=d[(1<<n)-1][i];
            poz=i;
        }
    }
    afisare((1<<n)-1,poz);
    return 0;
}