Cod sursa(job #1490716)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 24 septembrie 2015 01:13:02
Problema ADN Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 2.68 kb
#include <stdio.h>
#define INF 1000000000
#define MAXN 18
#define MAXK 30000
typedef struct{
    int a, b;
}mycreation;
mycreation last[1<<MAXN][MAXN];
int pi[MAXN][MAXK+1], k[MAXN], d[MAXN][MAXN], v[MAXN], dp[1<<MAXN][MAXN], ok[MAXN], ans[MAXN+1];
char m[MAXN][MAXK];
inline void precalc(int l){
    int i, r;
    pi[l][1]=r=0;
    for(i=2; i<=k[l]; i++){
        while((r)&&(m[l][r+1]!=m[l][i])){
            r=pi[l][r];
        }
        if(m[l][r+1]==m[l][i]){
            r++;
        }
        pi[l][i]=r;
    }
}
inline int kmp(int l, int c){
    int r, i;
    r=0;
    for(i=1; i<=k[l]; i++){
        while((r)&&(m[l][i]!=m[c][r+1])){
            r=pi[c][r];
        }
        if(m[c][r+1]==m[l][i]){
            r++;
        }
        if(r==k[c]){
            return k[c];
        }
    }
    return r;
}
int main(){
    int n, i, j, t, p;
    mycreation x, aux;
    char ch;
    FILE *fin, *fout;
    fin=fopen("adn.in", "r");
    fout=fopen("adn.out", "w");
    fscanf(fin, "%d ", &n);
    for(i=0; i<n; i++){
        ch=fgetc(fin);
        while(ch!='\n'){
            k[i]++;
            m[i][k[i]]=ch;
            ch=fgetc(fin);
        }
        precalc(i);
    }
    for(i=0; i<n; i++){
        for(j=0; j<n; j++){
            if(i!=j){
                d[i][j]=kmp(i, j);
                if(d[i][j]==k[j]){
                    ok[j]=1;
                }
            }
        }
    }
    t=0;
    for(i=0; i<n; i++){
        if(ok[i]==0){
            v[t++]=i;
            dp[1<<(t-1)][t-1]=k[i];
        }
    }
    for(i=0; i<(1<<t); i++){
        for(j=0; j<t; j++){
            if(dp[i][j]==0){
                dp[i][j]=INF;
                if((1<<j)&i){
                    for(p=0; p<t; p++){
                        if((j!=p)&&((1<<p)&i)&&(dp[i][j]>dp[i^(1<<j)][p]+k[v[j]]-d[v[p]][v[j]])){
                            dp[i][j]=dp[i^(1<<j)][p]+k[v[j]]-d[v[p]][v[j]];
                            last[i][j].a=i^(1<<j);
                            last[i][j].b=p;
                        }
                    }
                }
            }
        }
    }
    x.a=(1<<t)-1;
    x.b=0;
    for(i=1; i<t; i++){
        if(dp[x.a][x.b]>dp[x.a][i]){
            x.b=i;
        }
    }
    while(x.a!=0){
        ans[++ans[0]]=v[x.b];
        aux=last[x.a][x.b];
        x.a=aux.a;
        x.b=aux.b;
    }
    for(i=1; i<=k[ans[ans[0]]]; i++){
        fputc(m[ans[ans[0]]][i], fout);
    }
    for(i=ans[0]-1; i>0; i--){
        for(j=d[ans[i+1]][ans[i]]+1; j<=k[ans[i]]; j++){
            fputc(m[ans[i]][j], fout);
        }
    }
    fputc('\n', fout);
    fclose(fin);
    fclose(fout);
    return 0;
}