Cod sursa(job #3197467)

Utilizator Radu_MocanasuMocanasu Radu Radu_Mocanasu Data 26 ianuarie 2024 21:46:53
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.78 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
vector <string> adn(20, "");
int c[18][18];
int pi[60005];
int dp[(1 << 18)][18];
int last[(1 << 18)][18];
void kmp(int s1, int s2){
    int n,i,k = 0;
    string s = adn[s1] + adn[s2];
    pi[0] = 0;
    n = s.size();
    for(i = 1; i < n; i++){
        while(k > 0 && s[i] != s[k]) k = pi[k - 1];
        if(s[i] == s[k]) k++;
        pi[i] = k;
    }
    int m = min(adn[s1].size(), adn[s2].size());
    while(k > m) k = pi[k - 1];
    c[s2][s1] = k;
}
bool fnd(string s1, string s2){
    int i,k = 0,p = s1.size(), n = s2.size();
    pi[0] = 0;
    for(i = 1; i < p; i++){
        while(k > 0 && s1[i] != s1[k]) k = pi[k - 1];
        if(s1[k] == s1[i]) k++;
        pi[i] = k;
    }
    k = 0;
    for(i = 0; i < n; i++){
        while(k > 0 && s1[k] != s2[i]) k = pi[k - 1];
        if(s1[k] == s2[i]) k++;
        if(k == p) return 1;
    }
    return 0;
}
bool comp(const string &a, const string &b){
    return a.size() < b.size();
}
vector <int> sol;
vector <int> dl;
int main()
{
    int n,i,k,j,rez = 0x3f3f3f3f,t;
    fin >> n;
    for(i = 0; i < n; i++){
        fin.get();
        fin >> adn[i];
    }
    adn.resize(n);
    sort(adn.begin(), adn.end(), comp);
    for(i = 0; i < n; i++){
        for(j = i + 1; j < n; j++){
            if(fnd(adn[i], adn[j])){
                dl.push_back(i);
                break;
            }
        }
    }
    reverse(dl.begin(), dl.end());
    for(auto x : dl){
        n--;
        adn.erase(adn.begin() + x);
    }
    for(i = 0; i < n; i++){
        for(j = 0; j < n; j++){
            if(i == j) continue;
            kmp(i,j);
        }
    }
    memset(dp,0x3f,sizeof dp);
    for(i = 0; i < n; i++) dp[(1 << i)][i] = adn[i].size();
    for(k = 1; k < (1 << n); k++){
        for(i = 0; i < n; i++) if((1 << i) & k){
            for(j = 0; j < n; j++){
                if(i != j && (1 << j) & k){
                    if(dp[k][i] > dp[k ^ (1 << i)][j] + adn[i].size() - c[j][i]){
                        dp[k][i] = dp[k ^ (1 << i)][j] + adn[i].size() - c[j][i];
                        last[k][i] = j;
                    }
                }
            }
        }
    }
    for(i = 0; i <= n; i++){
        if(rez > dp[(1 << n) - 1][i]){
            rez = dp[(1 << n) - 1][i];
            t = i;
        }
    }
    k = (1 << n) - 1;
    for(i = n; i > 0; i--){
        int lt = t;
        sol.push_back(t);
        t = last[k][t];
        k ^= (1 << lt);
    }
    reverse(sol.begin(), sol.end());
    fout << adn[sol[0]];
    for(i = 1; i < sol.size(); i++){
        for(j = c[sol[i - 1]][sol[i]]; j < adn[sol[i]].size(); j++) fout << adn[sol[i]][j];
    }
    return 0;
}