Cod sursa(job #1464606)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 23 iulie 2015 23:38:17
Problema ADN Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.52 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int INF = 2e9, NMAX = 18, LENGTH_MAX = 30005;

char str[NMAX + 5][LENGTH_MAX];
int len[NMAX + 5];

int match[NMAX + 5][NMAX + 5];

int lmin[1 << NMAX][NMAX + 5];
int parent[1 << NMAX][NMAX + 5];

char solution[LENGTH_MAX * NMAX];
vector <int> res;

int kmp (int a, int b) {
    int i, p, pi[LENGTH_MAX];

    p = 0;
    pi[1] = 0;
    for(i = 2; i <= len[b]; ++ i) {
        while(p && str[b][p + 1] != str[b][i])
            p = pi[p];

        if(str[b][p + 1] == str[b][i])
            ++ p;
        pi[i] = p;
    }

    p = 0;
    for(i = 1; i <= len[a]; ++ i) {
        while(p && str[b][p + 1] != str[a][i])
            p = pi[p];
        if(str[b][p + 1] == str[a][i])
            ++ p;
    }

    return p;
}

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

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

    int i, n, j, subset, last, l, newSet;

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

    for (i = 0; i < n; ++ i)
        for (j = 0; j < n; ++ j)
            if (i != j)
                match[i][j] = kmp(i, j);

    for (subset = 1; subset < (1 << n); ++ subset)
        for (last = 0; last < n; ++ last)
            if (testBit(subset, last) && lmin[subset][last])
                for (i = 0; i < n; ++ i)
                    if (!testBit(subset, i)) {
                        newSet = subset | (1 << i);
                        if (lmin[newSet][i] == 0 || lmin[newSet][i] > lmin[subset][last] + len[i] - match[last][i]) {
                            lmin[newSet][i] = lmin[subset][last] + len[i] - match[last][i];
                            parent[newSet][i] = last;
                        }
                    }

    subset = (1 << n) - 1;
    l = INF;
    for (i = 0; i < n; ++ i)
        if (lmin[subset][i] && lmin[subset][i] < l) {
            l = lmin[subset][i];
            last = i;
        }

    while (subset) {
       i = parent[subset][last];

       res.push_back(last);
       subset ^= (1 << last);
       last = i;
    }

    reverse(res.begin(), res.end());

    strcat(solution, str[res[0]] + 1);
    for (i = 1; i < res.size(); ++ i)
        strcat(solution, str[res[i]] + 1 + match[res[i - 1]][res[i]]);
    printf("%s\n", solution);
    return 0;
}