Cod sursa(job #2964798)

Utilizator VartonVarts Var Varton Data 13 ianuarie 2023 22:32:42
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.64 kb
#include <fstream>
#include <cstring>
#include <vector>
#include <string>

using namespace std;

//ifstream in("maxflow.in");
//ofstream out("maxflow.out");

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

const int NMAX = 18;
const int INF  = 1000000;

string s, cuv[NMAX];
int pre[INF];
bool inclus[1 + NMAX];

vector<pair<int, int>> graf[NMAX];
int dp[1 << NMAX][NMAX];
pair<int, int> last[1 << NMAX][NMAX];



void kmp(int i, int j)
{

    memset(pre, 0, sizeof(pre));
    s = ' ' + cuv[i] + '$' + cuv[j];
    int pi = 0;

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

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


        pre[l] = pi;
        if (pi == cuv[i].size())
            inclus[i] = true;
    }

    graf[i].emplace_back(make_pair(j, cuv[i].size() - pre[s.size() - 1]));
}

string makeSol(int msBit, int nod)
{
    if (msBit == 0)
        return "";

    string s = makeSol(msBit - (1 << nod), last[msBit][nod].first);
    for (int i = cuv[nod].size() - last[msBit][nod].second; i < cuv[nod].size(); i++)
        s += cuv[nod][i];

    return s;
}

int main()
{

    int n;
    in >> n;

    for (int i = 0; i < n; i++)
        in >> cuv[i];

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (i != j)
                kmp(i, j);

    for (int msBit = 0; msBit < (1 << n); msBit++)
        for (int nod = 0; nod < n; nod++)
            dp[msBit][nod] = INF;
    for (int nod = 0; nod < n; nod++)
    {
        dp[1 << nod][nod] = cuv[nod].size();
        last[1 << nod][nod] = make_pair(-1, cuv[nod].size());
    }

    for (int msBit = 0; msBit < (1 << n); msBit++)
        for (int nod = 0; nod < n; nod++)
            if (!inclus[nod] && (msBit & (1 << nod)) != 0)
                for (auto& vecin : graf[nod])
                    if (!inclus[vecin.first] && (msBit & (1 << vecin.first)) != 0)
                        if (dp[msBit][nod] > dp[msBit - (1 << nod)][vecin.first] + vecin.second)
                        {
                            dp[msBit][nod] = dp[msBit - (1 << nod)][vecin.first] + vecin.second;
                            last[msBit][nod] = vecin;
                        }

    int sol = INF, solMask = (1<<n) - 1, solNod = -1;

    for (int i = 0; i < n; i++)
        if (inclus[i])
            solMask -= (1 << i);
    for (int i = 0; i < n; i++)
        if (!inclus[i] && sol > dp[solMask][i])
        {
            sol = min(sol, dp[solMask][i]);
            solNod = i;
        }


    out << makeSol(solMask, solNod) << '\n';
    return 0;
}