Cod sursa(job #3359609)

Utilizator Andrei_GAndreiG Andrei_G Data 1 iulie 2026 00:00:54
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.48 kb
#include <fstream>
#pragma GCC optimize("O3,unroll-loops")
#include <algorithm>
#include <cstring>
#include <climits>
#include <iomanip>
#include <numeric>
#include <bitset>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#define int long long
//#define int short
using namespace std;

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

const int nmax = 18;
const int lenmax = 3e4;

int n, scor[nmax + 5][nmax + 5], pi[2 * lenmax + 5], dp[nmax + 5][(1 << nmax) + 5];
string v[nmax + 5];

int calculatescor(int x, int y){
    string a = v[y] + "#" + v[x];
    for (int i = 1; i < a.size(); i++){
        int j = pi[i - 1];
        while (j && a[i] != a[j]){
            j = pi[j - 1];
        }
        if (a[i] == a[j]){
            j++;
        }
        pi[i] = j;
    }
    return pi[a.size() - 1];
}

void fastio(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
}

void handleinput(){
    cin>>n;
    for (int i = 0; i < n; i++){
        cin>>v[i];
    }
}

void setup(){
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            scor[i][j] = calculatescor(i, j);
        }
    }
    int cnt = 0;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            if (i != j && v[j].find(v[i]) != string::npos){
                v[i] = " ";
                break;
            }
        }
    }
    for (int i = 0; i < n - cnt; i++){
        while (i + cnt < n && v[i + cnt] == " "){
            cnt++;
        }
        if (i + cnt == n){
            break;
        }
        if (v[i + cnt] != " "){
            v[i] = v[i + cnt];
        }
    }
    n -= cnt;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            scor[i][j] = calculatescor(i, j);
        }
    }
    for (int mask = 0; mask < (1 << n); mask++){
        for (int i = 0; i < n; i++){
            dp[i][mask] = 1e9;
        }
    }
    for (int i = 0; i < n; i++){
        dp[i][(1 << i)] = v[i].size();
    }
    for (int mask = 1; mask < (1 << n); mask++){
        for (int i = 0; i < n; i++){
            if (!(mask & (1 << i))){
                continue;
            }
            for (int j = 0; j < n; j++){
                if (!(mask & (1 << j))){
                    dp[j][mask ^ (1 << j)] = min(dp[j][mask ^ (1 << j)], dp[i][mask] + (int)v[j].size() - scor[i][j]);
                }
            }
        }
    }
}

string buildanswer(){
    int last = 0, mask = (1 << n) - 1;
    for (int i = 0; i < n; i++){
        //cout<<dp[i][mask]<<" ";
        if (dp[last][mask] > dp[i][mask]){
            last = i;
        }
    }
    string rez;
    while (__builtin_popcount(mask) > 1){
        for (int i = 0; i < n; i++){
            if (!(mask & (1 << i)) || i == last){
                continue;
            }
            int newmask = mask ^ (1 << last);
            int cur = dp[last][mask];
            int cont = dp[i][newmask] + v[last].size() - scor[i][last];
            if (cont == cur && cur){
                rez = v[last].substr(scor[i][last]) + rez;
                mask = newmask;
                last = i;
                break;
            }
        }
    }
    return v[last] + rez;
}

void handleoutput(){
    cout<<buildanswer();
}

signed main(){
    fastio();
    handleinput();
    setup();
    handleoutput();
}


/*


*/