Cod sursa(job #2881217)

Utilizator bem.andreiIceman bem.andrei Data 30 martie 2022 12:46:32
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.13 kb
#include <bits/stdc++.h>

using namespace std;
ifstream r("adn.in");
ofstream w("adn.out");
const int INF=2000000000;
char s[19][30010];
int n, dp[(1<<19)][19], lg[19], p[30010], fth[(1<<19)][19], cst[19][19], f[19];
vector <pair<int,int> > L[19];
vector <int> v;

int main ()
{
    r>>n;
    for (int i=1; i<=n; i++)
    {
        r>>s[i]+1;
        lg[i] = strlen (s[i]+1);
    }
    for (int i=1; i<=n; i++)
    {
        memset(p, 0, sizeof(p));
        int l = 0;
        for (int j=2; j<=lg[i]; j++)
        {
            while (l && s[i][j] != s[i][l+1]){
                l = p[l];
            }
            if (s[i][j] == s[i][l+1]){
                l++;
            }
            p[j] = l;
        }
        for (int j=1; j<=n; j++)
        {
            if (i == j){
                continue;
            }
            int l = 0, ok = 0;
            for (int t=1; t<=lg[j]; t++)
            {
                while (l && s[j][t] != s[i][l+1]){
                    l = p[l];
                }
                if (s[j][t] == s[i][l+1]){
                    l++;
                }
                if (l == lg[i])
                {
                    ok = 1;
                    break;
                }
            }
            if (ok!=0)
            {
                L[i-1].push_back(make_pair(j-1,0));
                f[i] = 1;
                cst[j-1][i-1] = 0;
            }
            else
            {
                L[i-1].push_back(make_pair(j-1,lg[i] - l));
                cst[j-1][i-1] = lg[i] - l;
            }
        }
    }
    for (int i=0; i<(1<<n); i++){
        for (int j=0; j<n; j++){
            dp[i][j] = INF;
        }
    }
    int fin = 0;
    for (int i=0; i<n; i++){
        if (!f[i+1])
        {
            dp[(1<<i)][i] = lg[i+1];
            fin += (1<<i);
        }
    }
    for (int stare=1; stare<=fin; stare++)
    {

        for (int i=0; i<n; i++)
        {
            if (!(stare & (1<<i)) || f[i+1]){
                continue;
            }
            for (auto it : L[i])
            {
                int vecin = it.first, cost = it.second;
                if (!(stare & (1<<vecin)) || f[vecin+1]){
                    continue;
                }
                if (dp[stare-(1<<i)][vecin] + cost < dp[stare][i])
                {
                    dp[stare][i] = dp[stare-(1<<i)][vecin] + cost;
                    fth[stare][i] = vecin;
                }
            }
        }
    }
    int sol = INF, last = 0;
    for (int i=0; i<n; i++)
    {
        if (!f[i+1] && dp[fin][i] < sol)
        {
            sol = dp[fin][i];
            last = i;
        }
    }
    int x = fin, y = last;
    v.push_back(y);
    while (x)
    {
        int aux = (1<<y);
        y = fth[x][y];
        x -= aux;
        v.push_back(y);
    }
    v.pop_back();
    reverse(v.begin(),v.end());
    w<<s[v[0]+1]+1;
    for (int i=1; i<v.size(); i++)
    {
        int idx = v[i] + 1, val = cst[v[i-1]][v[i]];
        for (int j=lg[idx]-val+1; j<=lg[idx]; j++){
            w<<s[idx][j];
        }
    }
    return 0;
}