Cod sursa(job #3359259)

Utilizator rares89_Dumitriu Rares rares89_ Data 26 iunie 2026 13:15:36
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.11 kb
#include <bits/stdc++.h>

using namespace std;

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

const int INF = 1000000000;

int n, m;
string s[20], a[20];
int over[20][20], dp[1 << 18][18], tata[1 << 18][18];

vector<int> prefix(string p) {
    vector<int> pi(p.size());

    for(int i = 1; i < (int)p.size(); i++) {
        int j = pi[i - 1];

        while(j && p[i] != p[j]) {
            j = pi[j - 1];
        }

        if(p[i] == p[j]) {
            j++;
        }

        pi[i] = j;
    }

    return pi;
}

bool inside(string x, string y) {
    string t = x + "#" + y;
    vector<int> pi = prefix(t);

    for(int v : pi) {
        if(v == (int)x.size()) {
            return 1;
        }
    }

    return 0;
}

int getover(string x, string y) {
    int lg = min(x.size(), y.size());
    string t = y + "#" + x.substr(x.size() - lg);
    vector<int> pi = prefix(t);

    return pi.back();
}

int main() {
    fin >> n;

    for(int i = 0; i < n; i++) {
        fin >> s[i];
    }

    sort(s, s + n);
    n = unique(s, s + n) - s;

    for(int i = 0; i < n; i++) {
        int ok = 1;

        for(int j = 0; j < n; j++) {
            if(i != j && s[i].size() <= s[j].size() && inside(s[i], s[j])) {
                ok = 0;
                break;
            }
        }

        if(ok) {
            a[m++] = s[i];
        }
    }

    n = m;

    if(n == 0) {
        fout << "\n";
        return 0;
    }

    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(i != j) {
                over[i][j] = getover(a[i], a[j]);
            }
        }
    }

    int lim = 1 << n;

    for(int mask = 0; mask < lim; mask++) {
        for(int i = 0; i < n; i++) {
            dp[mask][i] = INF;
            tata[mask][i] = -1;
        }
    }

    for(int i = 0; i < n; i++) {
        dp[1 << i][i] = a[i].size();
    }

    for(int mask = 1; mask < lim; mask++) {
        for(int last = 0; last < n; last++) {
            if(dp[mask][last] == INF) {
                continue;
            }

            for(int nxt = 0; nxt < n; nxt++) {
                if(mask & (1 << nxt)) {
                    continue;
                }

                int nmask = mask | (1 << nxt);
                int val = dp[mask][last] + (int)a[nxt].size() - over[last][nxt];

                if(val < dp[nmask][nxt]) {
                    dp[nmask][nxt] = val;
                    tata[nmask][nxt] = last;
                }
            }
        }
    }

    int mask = lim - 1, last = 0;

    for(int i = 1; i < n; i++) {
        if(dp[mask][i] < dp[mask][last]) {
            last = i;
        }
    }

    vector<int> ord;

    while(last != -1) {
        ord.push_back(last);

        int p = tata[mask][last];
        mask ^= 1 << last;
        last = p;
    }

    reverse(ord.begin(), ord.end());

    string ans = a[ord[0]];

    for(int i = 1; i < (int)ord.size(); i++) {
        int x = ord[i - 1], y = ord[i];
        ans += a[y].substr(over[x][y]);
    }

    fout << ans;

    return 0;
}