Cod sursa(job #3358143)

Utilizator mirceamaierean41Mircea Maierean mirceamaierean41 Data 14 iunie 2026 21:51:18
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.04 kb
#include <fstream>
#include <iostream>
#include <stack>
#include <string.h>
#include <vector>

using namespace std;

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

const int NMAX = 3e4 + 1;
const int oo = 0x3f3f3f;
int dist[20][20];
int dp[19][1 << 19];
char parent[19][1 << 19];

int overlapKMP(string &a, string &b, bool &contained)
{
    string s = b + '#' + a;
    int m = s.size();
    vector<int> pi(m, 0);
    contained = false;

    for (int i = 1; i < m; ++i)
    {
        int k = pi[i - 1];
        while (k > 0 && s[i] != s[k])
            k = pi[k - 1];
        if (s[i] == s[k])
            ++k;
        pi[i] = k;
        if (k == b.size())
            contained = true;
    }

    return pi[m - 1];
}

int main()
{
    int n;
    fin >> n;
    bool contained[20] = {false};
    vector<string> sequences(n + 1);
    memset(dist, oo, sizeof(dist));
    for (int i = 1; i <= n; ++i)
    {
        fin >> sequences[i];
        dist[0][i] = sequences[i].size();
    }
    int finalMask = (1 << (n + 1)) - 1;
    for (int i = 1; i <= n; ++i)
    {
        if (contained[i])
            continue;
        for (int j = 1; j <= n; ++j)
        {
            if (contained[j] || i == j)
                continue;
            int overlap = overlapKMP(sequences[i], sequences[j], contained[j]);
            if (contained[j])
                finalMask = (finalMask ^ (1 << j));
            else
                dist[i][j] = sequences[j].size() - overlap;
        }
    }

    memset(dp, 0x3f3f3f3f, sizeof(dp));
    dp[0][1] = 0;

    for (int mask = 1; mask < (1 << (n + 1)); ++mask)
    {
        // check if mask is a subset of finalMask
        if ((mask & finalMask) != mask)
            continue;
        for (int j = 1; j <= n; j++)
        {
            if ((mask & (1 << j)) != 0)
            {
                int prev = mask - (1 << j);
                if (prev)
                {
                    for (int k = 0; k <= n; k++)
                    {
                        if ((prev & (1 << k)) != 0)
                        {
                            if (dp[j][mask] > dp[k][prev] + dist[k][j])
                            {
                                dp[j][mask] = dp[k][prev] + dist[k][j];
                                parent[j][mask] = k;
                            }
                        }
                    }
                }
            }
        }
    }

    stack<pair<int, int>> st;
    int ans = oo, last = -1;
    for (int j = 1; j <= n; ++j)
        if ((finalMask & (1 << j)) && dp[j][finalMask] < ans)
            ans = dp[j][finalMask], last = j;

    while (finalMask != 1)
    {
        st.push({last, ans});
        int newMask = finalMask ^ (1 << last);
        last = parent[last][finalMask];
        ans = dp[last][newMask];
        finalMask = newMask;
    }
    int prevLength = 0;
    while (!st.empty())
    {
        int lastDigitsLength = st.top().second - prevLength;
        fout << sequences[st.top().first].substr(sequences[st.top().first].size() - lastDigitsLength);
        prevLength = st.top().second;
        st.pop();
    }
    return 0;
}