Cod sursa(job #1017395)

Utilizator smaraldaSmaranda Dinu smaralda Data 27 octombrie 2013 19:02:41
Problema ADN Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.51 kb
#include<stdio.h>
#include<string.h>

const int NMAX = 18, LMAX = 30000, SUBM = 1 << 18;
char sir[NMAX + 5][LMAX + 5];
int sol[NMAX + 5],len[NMAX + 5],dp[SUBM + 5][20],vis[NMAX + 5],ok[NMAX + 5],pi[LMAX + 5],potriv[NMAX + 5][NMAX + 5];

void getPi (char *str) {
    int p,i,n;
    memset(pi,0,sizeof(pi));
    p = 0;
    n = strlen(str + 1);
    for(i = 2; i <= n; i++) {
        while(p && str[i] != str[p + 1])
            p = pi[p];
        if(str[i] == str[p + 1])
            ++p;
        pi[i] = p;
        }
}

int kmp (char *a, char *b) {
    int p,i,n,lenB;
    getPi(b);
    n = strlen(a + 1);
    lenB = strlen(b + 1);
    p = 0;
    for(i = 1; i <= n; i++) {
        while(p && a[i] != b[p + 1])
            p = pi[p];
        if(a[i] == b[p + 1])
            ++p;
        if(p == lenB)
            return lenB;
        }
    return p;
}

bool testBit (int x, int i) {
    return x & (1 << i);
}


int main() {
    freopen("adn.in","r",stdin);
    freopen("adn.out","w",stdout);
    int i,j,n,mic,k,newPos,val,last,size,aux,lim;

    scanf("%d\n",&n);
    for(i = 0; i < n; i++) {
        scanf("%s\n",sir[i] + 1);
        len[i] = strlen(sir[i] + 1);
        }

    for(i = 0; i < n; i++)
        for(j = 0; j < n; j++) {
            potriv[i][j] = kmp(sir[i],sir[j]);
            if(i != j && potriv[i][j] == len[j])
                ok[j] = 1;
            }

    lim = 0;
    for(j = 0; j < n; j++)
        if(!ok[j]) {
            dp[1 << j][j] = len[j];
            lim = lim | (1 << j);
            }

    for(i = 1; i <= lim; i++)
        for(j = 0; j < n; j++)
            if(!ok[j] && dp[i][j] && testBit(i,j))
                for(k = 0; k < n; k++) {
                    newPos = i + (1 << k);
                    val = dp[i][j] + len[k] - potriv[j][k];
                    if(!ok[k] && !testBit(i,k) && newPos <= lim && (dp[newPos][k] == 0 || val < dp[newPos][k]))
                        dp[newPos][k] = val;
                    }

    size = last = 0;
    while(lim) {
        mic = LMAX + 1;
        for(j = 0; j < n; j++)
            if(testBit(lim,j) && dp[lim][j] && dp[lim][j] < mic && !vis[j]) {
                mic = dp[lim][j];
                last = j;
                }
        sol[++size] = last;
        vis[last] = 1;
        lim = lim - (1 << last);
        }

    printf("%s",sir[sol[size]] + 1);
    for(i = size - 1; i > 0; i--)
        printf("%s",sir[sol[i]] + 1 + potriv[sol[i + 1]][sol[i]]);
    printf("\n");
    return 0;
}