Cod sursa(job #2922791)

Utilizator VladPislaruPislaru Vlad Rares VladPislaru Data 10 septembrie 2022 09:55:43
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.59 kb
#include <bits/stdc++.h>

using namespace std;

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

const int MaxN = 18;
const int MaxL = 30001;


string cuvinte[MaxN];

string s;
int prefix[5 + 2 * MaxL];

bool inclus[1 + MaxN];

int mat[MaxN][MaxN];

int dp[1 << MaxN][MaxN];

pair<int, int> last[1 << MaxN][MaxN]; /// last.first -> node, last.second -> len

void KMP(int cuv1, int cuv2)
{
    memset(prefix, 0, sizeof(prefix));
    s = ' ' + cuvinte[cuv1] + ' ' + cuvinte[cuv2];

    int pi = 0;

    for (int i = 2; i < s.size(); i++)
    {
        while (pi > 0 && s[i] != s[pi + 1])
          pi = prefix[pi];

        if (s[i] == s[pi + 1])
          pi++;

        prefix[i] = pi;

        if (pi == cuvinte[cuv1].size())
          inclus[cuv1] = true;
    }
    mat[cuv1][cuv2] = cuvinte[cuv1].size() - prefix[s.size() - 1];
}

string Solve(int bit, int nod)
{
    if (bit == 0)
    return "";

    string s = Solve(bit - (1 << nod), last[bit][nod].first);

    for (int i = cuvinte[nod].size() - last[bit][nod].second; i < cuvinte[nod].size(); i++)
        s += cuvinte[nod][i];
    return s;
}

int main()
{
    int n;
    fin >> n;

    for (int i = 0; i < n; i++)
        fin >> cuvinte[i];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
           if (i != j)
            KMP(i, j);
    for (int bit = 0; bit < (1 << n); bit++)
        for (int nod = 0; nod < n; nod++)
            dp[bit][nod] = 1e9;
    for (int nod = 0; nod < n; nod++)
    {
        dp[1 << nod][nod] = cuvinte[nod].size();
        last[1 << nod][nod] = make_pair(-1, cuvinte[nod].size());
    }
    for (int bit = 0; bit < (1 << n); bit++)
        for (int nod = 0; nod < n; nod++)
            if (!inclus[nod] && (bit & (1 << nod)) != 0)
                for (int vec = 0; vec < n; vec++)
                    if (vec != nod && !inclus[vec] && (bit & (1 << vec)) != 0)
                        if (dp[bit][nod] > dp[bit - (1 << nod)][vec] + mat[nod][vec])
                        {
                          dp[bit][nod] = dp[bit - (1 << nod)][vec] + mat[nod][vec];
                          last[bit][nod] = {vec, mat[nod][vec]};
                        }
    int sol_mask = (1 << n) - 1;
    int node = -1;
    int sol = 1e9;
    for (int i = 0; i < n; i++)
        if (inclus[i])
            sol_mask -= (1 << i);

    for (int i = 0; i < n; i++)
        if (!inclus[i] && sol > dp[sol_mask][i])
        {
            node = i;
            sol = min(sol, dp[sol_mask][i]);
        }
    fout << Solve(sol_mask, node) << "\n";
    return 0;
}