Cod sursa(job #1488217)

Utilizator iordache.bogdanIordache Ioan-Bogdan iordache.bogdan Data 18 septembrie 2015 10:19:56
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.28 kb
#include <fstream>
#include <cstring>
#include <algorithm>
#include <vector>

#define DIM 18
#define LEN 30005
#define infile "adn.in"
#define outfile "adn.out"

using namespace std;

ifstream fin(infile);
ofstream fout(outfile);

char seq[DIM + 1][LEN];

int pi[DIM + 1][LEN];

int cost[DIM +1][DIM + 1];

int sol[DIM + 1], w[DIM + 1];

bool useless[DIM];

int dp[1 << DIM][DIM + 1], t[1 << DIM][DIM + 1];

int main() {

    int n;

    fin >> n;

    for (int i = 1; i <= n; ++i) {

        fin >> seq[i] + 1;

    }

    //prefix function

    for (int i = 1; i <= n; ++i) {

        int q;

        for (int j = 2; seq[i][j]; ++j) {

            q = pi[i][j - 1];

            while (q && seq[i][j] != seq[i][q + 1])
                q = pi[i][q];

            if (seq[i][j] == seq[i][q + 1])
                pi[i][j] = q + 1;

        }

    }

    //merge cost

    for (int i = 1; i <= n; ++i) {

        for (int j = 1; j <= n; ++j) {

            if (i == j)
                continue;

            cost[i][j] = -1;

            int q = 0;

            for (int pos = 1; seq[i][pos]; ++pos) {

                while (q && seq[i][pos] != seq[j][q + 1])
                    q = pi[j][q];

                if(seq[i][pos] == seq[j][q + 1])
                    ++q;

                if (q == strlen(seq[j] + 1)) {

                    cost[i][j] = 0;

                    useless[j] = true;

                    break;

                }

            }

            if (cost[i][j] == -1) {

                cost[i][j] = strlen(seq[j] + 1) - q;

            }

        }

    }

    int m = 0;

    for (int i = 1; i <= n; ++i)
        if (!useless[i])
            w[++m] = i;


    //dynamic programming

    for (int config = 1, i = 1; config < (1 << m); config <<= 1, ++i) {

        dp[config][i] = 0;

        t[config][i] = -1;

    }


    for (int config = 1; config < (1 << m); ++config) {

        if (!(config & (config - 1)))
            continue;

        for (int i = 1; i <= m; ++i) {

            if (!(config & (1 << (i - 1))))
                continue;

            dp[config][i] = 2000000000;

            t[config][i] = -1;

            for (int j = 1; j <= m; ++j) {

                if (i == j || !(config & (1 << (j - 1))))
                    continue;

                int aux = dp[config ^ (1 << (i - 1))][j] + cost[w[j]][w[i]];

                if (aux < dp[config][i]) {

                    dp[config][i] = aux;

                    t[config][i] = j;

                }

            }

        }

    }


    int last, minim = 2000000000;

    for (int i = 1; i <= m; ++i) {

        if (minim > dp[(1 << m) - 1][i]) {

            minim = dp[(1 << m) - 1][i];

            last = i;

        }

    }

    int nr = 0, config = (1 << m) - 1;

    while (last != -1) {

        sol[++nr] = w[last];

        last = t[config][last];

        config ^= (1 << (last - 1));

    }

    fout << seq[sol[nr]];

    for (int i = nr - 1; i; --i) {

        for (int j = strlen(seq[sol[nr]] + 1) - cost[sol[nr + 1]][sol[nr]] + 1; seq[sol[nr]][j]; ++j)
            fout << seq[sol[nr]][j];

    }

    return 0;

}

//Trust me, I'm the Doctor!