Cod sursa(job #1001272)

Utilizator FlameingoAiordachioaei Marius Flameingo Data 24 septembrie 2013 19:51:22
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.66 kb
#include <cstdio>
#include <cstring>
#include <bitset>
#include <stack>
#define ml first
#define prev second.first
#define niv second.second
using namespace std;

const int NMAX = 19, LMAX = 30003;

bitset <NMAX> valid;
pair <int, pair <int, int> > D[1 << NMAX - 1][NMAX];
stack <short> order;
short prefix[NMAX][LMAX], lengths[NMAX], cost[NMAX][NMAX];
char s[NMAX][LMAX];

inline void make_prefix (char *S, short *V, const short len) {

    short i, k = 0;
    for (i = 2; i <= len; ++i) {
        while (k && S[k + 1] != S[i])
            k = V[k];
        if (S[k + 1] == S[i])
            ++k;
        V[i] = k;
    }

}

inline int make_cost (const short &x, const short &y) {

    short i, k = 0;
    for (i = 1; i <= lengths[x]; ++i) {
        while (k && s[x][i] != s[y][k + 1])
            k = prefix[y][k];
        if (s[x][i] == s[y][k + 1])
            ++k;
        if (k == lengths[y]) {
            valid[y] = 0;
            return -1;
        }
    }
    return k;

}

int main () {

    freopen ("adn.in", "r", stdin);
    freopen ("adn.out", "w", stdout);
    int i, l, j, k, a;
    short N;
    scanf ("%d\n", &N);
    valid.set ();
    for (i = 1; i <= N; ++i) {
        fgets (s[i] + 1, LMAX, stdin);
        lengths[i] = strlen (s[i] + 1);
        s[i][lengths[i]--] = 0;
        make_prefix (s[i], prefix[i], lengths[i]);
        for (j = i - 1; j; --j)
            cost[i][j] = make_cost (i, j),
            cost[j][i] = make_cost (j, i);
    }
    l = 1 << N;
    for (i = 1; i < l; ++i) {
        for (j = 1; j <= N; ++j) /// in j se termina
            if (i & 1 << (j - 1) && valid[j]) {
                for (k = 1; k < j; ++k)
                    if (i & 1 << (k - 1) && valid[k] && cost[k][j] + D[i ^ (1 << j - 1)][k].ml >= D[i][j].ml)
                            D[i][j] = make_pair (cost[k][j] + D[i ^ (1 << j - 1)][k].ml, make_pair (k, i ^ (1 << j - 1)));
                for (k = j + 1; k <= N; ++k)
                    if (i & 1 << (k - 1) && valid[k] && cost[k][j] + D[i ^ (1 << j - 1)][k].ml >= D[i][j].ml)
                            D[i][j] = make_pair (cost[k][j] + D[i ^ (1 << j - 1)][k].ml, make_pair (k, i ^ (1 << j - 1)));

            }
    }
    i = 1;
    for (j = 2; j <= N; ++j)
        if (D[l - 1][i].ml < D[l - 1][j].ml)
            i = j;
    j = l - 1;
    k = i;
    while (k)
        order.push (k),
        a = k,
        k = D[j][k].prev,
        j = D[j][a].niv;
    printf ("%s", s[k = order.top ()] + 1);
    order.pop ();
    while (!order.empty ())
        printf ("%s", &s[order.top ()][cost[k][order.top ()] + 1]),
        k = order.top (),
        order.pop ();

}