Cod sursa(job #949392)

Utilizator robertstrecheStreche Robert robertstreche Data 13 mai 2013 17:39:48
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.75 kb
#include <fstream>
#include <cstring>
#include <iostream>
using namespace std;

#define MAXN 19
#define MAXDIM 31000
#define INF 0x3f3f3f3f

ifstream fin("adn.in");
ofstream fout("adn.out");

int N, pre[MAXDIM], len[MAXN], inside[MAXN], dist[MAXN][MAXN], prev[1 << (MAXN - 1)][MAXN], rez[1 << (MAXN - 1)][MAXN];
char sir[MAXN][MAXDIM];

void read() {
    fin >> N; fin.get();

    for (int i = 1; i <= N; ++i) {
        fin.getline(sir[i] + 1, MAXDIM);
        len[i] = strlen(sir[i] + 1);
    }
}

void make_prefix(int x) {
    pre[1] = 0;

    for (int i = 2, k = 0; i <= len[x]; ++i) {
        while (k > 0 && sir[x][k + 1] != sir[x][i])
            k = pre[k];
        if (sir[x][k + 1] == sir[x][i])
            ++k;
        pre[i] = k;
    }
}

void doKMP(int x, int y) {
    int k = 0;

    for (int i = 1; i <= len[y]; ++i) {
        while (k > 0 && sir[x][k + 1] != sir[y][i])
            k = pre[k];
        if (sir[x][k + 1] == sir[y][i])
            ++k;
        if (k == len[x]) {
            inside[x] = 1;
            break;
        }
    }

    dist[y][x] = len[x] - k;
}

void do_graph() {
    for (int i = 1; i <= N; ++i) {
        make_prefix(i);
        for (int j = 1; j <= N; ++j)
            if (i != j && !inside[j])
                doKMP(i, j);
    }
}

void solve_next(int conf, int last) {
    for (int k = 1; k <= N; ++k)
        if (k != last && !inside[k])
            if (rez[conf + (1 << (k - 1))][k] > rez[conf][last] + dist[last][k]) {
                rez[conf + (1 << (k - 1))][k] = rez[conf][last] + dist[last][k];
                prev[conf + (1 << (k - 1))][k] = last;
            }
}

void solve() {

    memset(rez, INF, sizeof(rez));

    for (int i = 1; i <= N; ++i)
        if (!inside[i])
            rez[1 << (i - 1)][i] = len[i];

    for (int i = 1; i < (1 << N); ++i) {
        for (int j = 1; j <= N; ++j)
            if (rez[i][j] != INF && ((i & (1 << (j - 1))) != 0))
                solve_next(i, j);
    }
}

void print_recursion(int conf, int last, int pot) {
    if (prev[conf][last] != 0)
        print_recursion (conf - (1 << (last - 1)), prev[conf][last], len[last] - dist[prev[conf][last]][last]);

    for (int i = 1; i <= len[last] - pot; ++i)
        fout << sir[last][i];
}


void print() {
    int maxCONF = (1 << N) - 1;
    int minDIM = INF, minPOZ;

    for (int i = 1; i <= N; ++i)
        if (inside[i])
            maxCONF -= 1 << (i - 1);

    for (int i = 1; i <= N; ++i) {
        if (rez[maxCONF][i] < minDIM) {
            minDIM = rez[maxCONF][i];
            minPOZ = i;
        }
    }

    print_recursion(maxCONF, minPOZ, 0);
}

int main() {
    read();
    do_graph();
    solve();
    print();
    return 0;
}