Cod sursa(job #2467751)

Utilizator mihneacazCazacu Mihnea mihneacaz Data 4 octombrie 2019 23:46:44
Problema ADN Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.26 kb
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

const int NMAX = 22;
const int LMAX = 30005;

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

int cut[NMAX];
int len[NMAX][NMAX];
int dp[(1 << 18)][NMAX];
int k[LMAX * 2];
int recon[(1 << 18)][NMAX];

int kmp(string a, string b)
{
    string s;
    s="?" + a;
    s=s + "#";
    s=s + b;
    for(int i=0; i < (int)s.size(); ++ i)
        k[i] = 0;
    for(int i = 2; i < (int)s.size(); ++ i) {
        int q = k[i-1];
        while(q && s[i] != s[q+1])
            q = k[q];
        if(s[q+1] == s[i])
            ++ q;
        k[i] = q;
    }
    return k[s.size() - 1];
}
int main()
{
    vector <string> initial;
    vector <string> v;
    int n;
    cin>>n;
    for(int i = 1; i <= n; ++ i) {
        string s;
        cin>>s;
        initial.push_back(s);
    }
    for(int i = 0; i < (int)initial.size(); ++ i) {
        for(int j = 0; j < (int)initial.size(); ++ j) {
            if(i != j && (int)initial[j].size() >= (int)initial[i].size() && cut[j] == 0) {
                for(int st = 0; st <= (int)initial[j].size() - (int)initial[i].size(); ++ st) {
                    bool ok = 1;
                    for(int k = st; k <= st + (int)initial[i].size() - 1; ++k) {
                        if(initial[j][k] != initial[i][k - st]) {
                            ok = 0;
                            break;
                        }
                    }
                    if(ok == 1) {
                        cut[i] = 1;
                        break;
                    }
                }
            }
        }
        if(cut[i] == 0)
            v.push_back(initial[i]);
    }
    n = v.size();
    for(int i = 0; i < n; ++ i)
        for(int j = 0; j < n; ++ j)
            if(i != j)
                len[i][j] = kmp(v[i], v[j]);
    for(int i = 0; i < n; ++ i) {
        dp[1 << i][i] = (int)v[i].size();
        recon[1 << i][i] = -1;
    }
    for(int masca = 1; masca <= (1 << n) - 1; ++ masca)
        for(int bit = 0; bit < n; ++ bit)
            if(masca & (1 << bit))
                for (int new_bit = 0 ; new_bit < n; ++ new_bit)
                    if(!(masca & (1 << new_bit))) {
                        if(dp[masca | (1 << new_bit)][new_bit] == 0 || (dp[masca | (1 << new_bit)][new_bit] > dp[masca][bit] + (int)v[new_bit].size() - len[bit][new_bit])) {
                            dp[masca | (1 << new_bit)][new_bit] = dp[masca][bit] + (int)v[new_bit].size() - len[bit][new_bit];
                            recon[masca | (1 << new_bit)][new_bit] = bit;
                        }
                    }
    int ans = dp[(1 << n) - 1][0];
    int last = 0;
    for(int j = 1; j < n; ++ j) {
        if(dp[(1 << n) - 1][j] < ans) {
            ans = dp[(1 << n) - 1][j];
            last = j;
        }
    }
    int masca = (1 << n) - 1;
    int prec = 0;
    while(prec != -1) {
        int prec = recon[masca][last];
        if(prec == -1) {
            cout<<v[last]<<"\n";
            return 0;
        }
        for(int i = 0; i < (int)v[last].size() - len[prec][last]; ++ i)
            cout<<v[last][i];
        masca = masca - (1 << last);
        last = prec;
    }
    return 0;
}