Cod sursa(job #1536366)

Utilizator StarGold2Emanuel Nrx StarGold2 Data 26 noiembrie 2015 00:33:12
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.83 kb
#include <cstdio>
#include <cstring>

#define DIM1 18
#define DIM2 32768
#define INF 10000000
using namespace std;

int K, N, MIN, POS, len, Q;
int D[(1<<DIM1)][DIM1], T[(1<<DIM1)][DIM1], C[DIM1][DIM1];
char String[DIM1][DIM2], c; int S[DIM1], Seen[DIM1], V[DIM1];

int getSuffix (char String1[], char String2[]) {
    int Prefix[DIM2], N, M, K; Prefix[0] = -1;

    N = strlen (String1);
    M = strlen (String2);

    K = -1;
    for (int i = 1; i < N; i ++) {
        while (K != -1 && String1[K+1] != String1[i])
            K = Prefix[K];

        if (String1[K+1] == String1[i])
            K += 1;

        Prefix[i] = K;
    }

    K = -1;
    for (int i = 1; i < M; i ++) {
        while (K != -1 && String1[K+1] != String2[i])
            K = Prefix[K];

        if (String1[K+1] == String2[i])
            K ++;

        if (K == N - 1) // al 2-lea sir e inclus complet in primul deci nu il mai numar
            return 0;
    }

    return N-K-1; // nu e inclus deci ii iau doar finalul (N-K-1)
}

void DFS (int val, int pos) {
    if (val == 0)
        return;
    else {
        S[++K] = V[pos];
        DFS (val - (1<<pos), T[val][pos]);
    }
    return;
}

int main () {

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

    scanf ("%d", &N);
    scanf ("%c", &c);
    for (int i = 0; i < N; i ++)
        scanf ("%s", String[i]);

    for (int i = 0; i < N; i ++)
    for (int j = 0; j < N; j ++) {
        if (i != j) {
            C[i][j] = getSuffix (String[j], String[i]);
            if (!C[i][j]) Seen[j] = 1; /* INSPIRED */
        }
    }

    for (int i = 0; i < (1<<N); i ++)
    for (int j = 0; j < N; j ++)
        D[i][j] = INF;
/* INSPIRED */
    for (int i = 0; i < N; i ++) {
        if (Seen[i])
            continue;

        V[Q] = i;
        D[(1<<Q)][Q++] = strlen (String[i]);
    }
/* INSPIRED */
    for (int i = 1; i < (1<<N); i ++)
    for (int j = 0; j < N; j ++) {

        if (!(i & (1<<j)))
            continue;

        for (int k = 0; k < N; k ++) {

            if (!(!((i>>k)&1)))
                continue;

            if (D[i+(1<<k)][k] > D[i][j] + C[V[j]][V[k]]) {
                D[i+(1<<k)][k] = D[i][j] + C[V[j]][V[k]];
                T[i+(1<<k)][k] = j;
            }
        }
    }

    MIN = INF;
    for (int i = 0; i < N; i ++) {
        if (D[(1<<N)-1][i] < MIN) {
            MIN = D[(1<<N)-1][i];
            POS = i;
        }
    }

    DFS ((1<<N)-1, POS);

    len = strlen (String[S[K]]);

    for (int i = 0; i < len; i ++)
        printf ("%c", String[S[K]][i]);

    K --;
    while (K) {
        len = strlen (String[S[K]]);

        for (int i = len - C[S[K+1]][S[K]]; i < len; i ++)
            printf ("%c", String[S[K]][i]);

        K --;
    }

    return 0;
}