Cod sursa(job #3333714)

Utilizator GabiRB1Rafael GabiRB1 Data 14 ianuarie 2026 22:22:49
Problema ADN Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.28 kb
#include <bits/stdc++.h>

using namespace std;
string s[20];
int c[20][20];
bool included(string &s1, string &s2)
{
    return s2.find(s1) != string::npos;
}
bool deleteString(int i, int j)
{
    if(s[i].length() <= s[j].length())
    {
        if(included(s[i], s[j]))
            return 1;
    }
    //else if(included(s[j], s[i]))
    //  return 1;
    return 0;
}

string s3 = "";
int calc(string &s1, string &s2, string &s3)
{
    unordered_set<int> s;
    long long b = 137, mod = 1e9 + 7, nr = 0, p = 1;
    for(int i = s1.length() - 1; i >= 0; i --)
        nr = nr + (s1[i] - 'A' + 1) * p, nr %= mod, p *= b, p %= mod, s.insert(nr);

    nr = 0;
    int maxx = 0;
    for(int i = 0; i < s2.length(); i ++)
    {
        nr = nr * b % mod + s2[i] - 'A' + 1, nr %= mod;
        if(s.find(nr) != s.end())
            maxx = i + 1;
    }

    if(s3 != "")
    {
        for(int i = maxx; i < s2.length(); i ++)
            s3 += s2[i];
    }
    return s2.length() - maxx;

}


int dp[19][19][(1 << 18) + 5], n;
short t[19][19][(1 << 18) + 6];
int main()
{
    ifstream f("adn.in");
    ofstream g("adn.out");
    f >> n;
    for(int i = 0; i < n; i ++)
        f >> s[i];
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            if(i != j)
                if(deleteString(i, j))
                {
                    for(int p = i; p < n - 1; p ++)
                        s[p] = s[p + 1];
                    n --;
                    i --;
                    break;
                }

    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            c[i][j] = calc(s[i], s[j], s3);


    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            for(int p = 0; p < (1 << n); p ++)
            dp[i][j][p] = 1e9;

    for(int i = 0; i < n; i ++)
        dp[i][i][(1 << i)] = s[i].length();


    for(int start = 0; start < n; start ++)
    {
        for(int mask = 1; mask < (1 << n); mask ++)
        {
            for(int i = 0; i < n; i ++)
                if(mask & (1 << i))
                {
                    int prev = mask ^ (1 << i);
                    for(int j = 0; j < n; j ++)
                        if(prev & (1 << j)){
                                if(dp[start][j][prev] + c[i][j] <= dp[start][i][mask])
                                    dp[start][i][mask] = min(dp[start][i][mask], dp[start][j][prev] + c[j][i]),
                                    t[start][i][mask] = j;
                        }
                }
        }
    }

    int minn = 1e9, pozi, pozj, mask = (1 << n) - 1;
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++){
                if(dp[i][j][mask] < minn)
                    minn = min(minn, dp[i][j][mask]), pozi = i, pozj = j;
        }

    vector<int> rez;
    rez.push_back(pozj);
    while(mask != (1 << pozi))
    {
        rez.push_back(t[pozi][pozj][mask]);
        int aux = t[pozi][pozj][mask];
        mask = mask ^ (1 << pozj);
        pozj = aux;
    }
    string s_Rez = "";
    reverse(rez.begin(), rez.end());
    s_Rez = s[rez[0]];

    for(int i = 1; i < n; i ++)
    {
        calc(s[rez[i - 1]], s[rez[i]], s_Rez);
    }
    g << s_Rez;
    //g << minn;


    return 0;
}