Cod sursa(job #2962117)

Utilizator Katherine456719Swan Katherine Katherine456719 Data 7 ianuarie 2023 19:36:23
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.25 kb
#include <bits/stdc++.h>

using namespace std;


int n;
vector<string> siruri;
vector<string> corecte;
vector<bool> ok;
int ant[20][1 << 20];
int dp[20][500000], cost[20][20];
ofstream fout("adn.out");
int KMP(string &str1, string &str2) {
    vector<int> kmp = vector<int>(str1.size() + str2.size() + 5, 0);
    string s;
    s += '#' + str1;
    int l2, l1 = (int) s.size() - 1, cont = 0;
    s += '&' + str2;
    l2 = (int) s.size() - 1;

    kmp[1] = 0;
    for (int i = 2; i <= l2; ++i) {
        int k = i - 1;
        while (k && s[i] != s[kmp[k] + 1])
            k = kmp[k];
        if (s[i] == s[kmp[k] + 1])
            kmp[i] = kmp[k] + 1;
        else kmp[i] = 0;
        if (kmp[i] == l1)
            cont++;
    }
    //returnam lungimea daca e continut
    if (cont >= 1)
        return l1;
    //returnam nr de caractere comune
    return kmp[l2];
}

void Hamilton_cost_maxim() {
    int total = (1 << n) - 1;

    for (int mask = 0; mask <= total; mask++) {
        for (int sf = 0; sf < n; sf++) {

            if ((mask & (1 << sf)) == 0)
                continue;

            for (int anterior = 0; anterior < n; anterior++) {
                if (anterior == sf)
                    continue;

                if ((mask & (1 << anterior)) == 0)
                    continue;
                int c = dp[anterior][mask ^ (1 << sf)] + cost[anterior][sf];
                if (dp[sf][mask] <= c) {
                    dp[sf][mask] = c;
                    ant[sf][mask] = anterior;
                }
            }
        }
    }
    int current = 0;
    for (int i = 0; i < n; i++) {
        if (dp[current][total] < dp[i][total]) {
            current = i;
        }
    }


    vector<int> drum;
    int mask = total;

    while (mask != 0) {
        drum.push_back(current);
        int ant_mask = mask ^ (1 << current);
        int nod_ant = ant[current][mask];

        current = nod_ant;
        mask = ant_mask;
    }

    reverse(drum.begin(), drum.end());
    int skip_next = 0;

    for (int i = 0; i < n; i++) {
        int node = drum[i];
        string s = corecte[node].substr(skip_next);
        fout << s;
        if (i != n - 1) {
            skip_next = cost[node][drum[i + 1]];
        }
    }

}

int main() {
    ifstream fin("adn.in");

    fin >> n;
    ok.resize(n + 1, true);
    for (int i = 0; i < n; ++i) {
        string a;
        fin >> a;
        siruri.push_back(a);
    }

    for (int i = 0; i <= n; ++i)
        for (int j = 0; j <= n; ++j)
            cost[i][j] = -1;

    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            if (i != j) {
                int comune = KMP(siruri[i], siruri[j]);
                if (comune == siruri[i].size()) {
                    ok[i] = false;
                }
            }


    for (int i = 0; i < n; ++i) {
        if (ok[i]) {
            corecte.push_back(siruri[i]);
        }
    }

    n = (int) corecte.size();
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            if (i != j) {
                int comune = KMP(corecte[j], corecte[i]);
                cost[i][j] = comune;
            }

    Hamilton_cost_maxim();

    return 0;
}