Cod sursa(job #3359550)

Utilizator chisianisChis Ianis-Alexandru chisianis Data 29 iunie 2026 22:35:47
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.1 kb
#include <bits/stdc++.h>
using namespace std;
#define FASTIO ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);

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

int lps[60010], dp[1 << 18][18], p[1 << 18][18];

bool is_included(string a, string b)
{
    int n = a.length(), m = b.length();
    if(m <= n) return 0;
    int k = 0;
    for(int i = 2; i <= n; i++){
	    while(k != 0 && a[k] != a[i - 1]) 
		    k = lps[k]; 
	    if(a[k] == a[i - 1]) k++;
        lps[i] = k;
    }
    k = 0;
    int nrs = 0;
    for(int i = 1; i <= m; i++){
        while(k != 0 && a[k] != b[i - 1])
            k = lps[k];
        if(a[k] == b[i - 1]) k++;
        if(k == n) return 1;
    }
    return 0;
}

int calculate_cost(string a, string b){
    string x = b + "#" + a;
    int n = x.size();
    int k = 0;
    for(int i = 2; i <= n; i++){
        while(k != 0 && x[k] != x[i - 1])
            k = lps[k];
        if(x[k] == x[i - 1]) k++;
        lps[i] = k;
    }
    return b.size() - lps[n];
}

int main()
{
FASTIO
    
    int n; fin >> n;
    vector<string> a;
    for(int i = 1; i <= n; i++){
        string x; fin >> x;
        a.push_back(x);
    }
    vector<bool> nv(n);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(i != j && (is_included(a[i], a[j]) || (i < j && a[i] == a[j]))) nv[i] = 1;
    vector<string> s;
    for(int i = 0; i < n; i++)
        if(!nv[i]) s.push_back(a[i]);
    n = s.size();
    vector<vector<int>> c(20, vector<int>(20));
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(i != j) c[i][j] = calculate_cost(s[i], s[j]);
    for(int mask = 0; mask < (1 << n); mask++){
        for(int i = 0; i < n; i++){
            dp[mask][i] = 1e9;
            p[mask][i] = -1;
        }
    }
    for(int i = 0; i < n; i++){
        dp[1 << i][i] = s[i].length();
    }
    for(int mask = 1; mask < (1 << n); mask++)
        for(int i = 0; i < n; i++){
            if(!(mask & (1 << i))) continue;
            if(dp[mask][i] == 1e9) continue;
            for(int j = 0; j < n; j++){
                if(!(mask & (1 << j))){
                    int nmask = mask | (1 << j);
                    if(dp[mask][i] + c[i][j] < dp[nmask][j]){
                        dp[nmask][j] = dp[mask][i] + c[i][j];
                        p[nmask][j] = i;
                    }
                }
            }
        }
    int mn = 2e9;
    int ult = -1;
    int fmask = (1 << n) - 1;
    for(int i = 0; i < n; i++){
        if(dp[fmask][i] < mn){
            mn = dp[fmask][i];
            ult = i;
        }
    }
    vector<int> ord;
    int curr_mask = fmask;
    while(ult != -1){
        ord.push_back(ult);
        int prv = p[curr_mask][ult];
        curr_mask ^= (1 << ult);
        ult = prv;
    }
    reverse(ord.begin(), ord.end());
    string sol = s[ord[0]];
    n = ord.size();
    for(int i = 1; i < n; i++){
        int a = ord[i-1];
        int b = ord[i];
        sol += s[b].substr(s[b].length() - c[a][b]);
    }
    fout << sol << "\n";

    return 0;
}