Cod sursa(job #2216159)

Utilizator NOSCOPEPROKENDYMACHEAMACUMVREAU NOSCOPEPROKENDY Data 25 iunie 2018 16:15:57
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.02 kb
#include <bits/stdc++.h>
using namespace std;

int n;
char s[19][31005];
int c[19], cost[19][19];
int pi[19][31005];
int d[272144][19];
int TT[272144][19];
vector <int> Sol;
inline void ma(char s[], int pi[]){
    pi[1] = 0;
    int n = strlen(s + 1);
    for(int i = 2; i <= n ; ++i){
        int q = pi[i - 1];
        while(q && s[q + 1] != s[i])
            q = pi[q];
        if(s[q + 1] == s[i]) ++q;
        pi[i] = q;
    }
}
inline int gi(char a[], char b[], int pi[]){
    int q = 0;
    int n = strlen(b + 1);
    for(int i = 1; i <= n ; ++i){
        while(a[q + 1] != b[i] && q)
            q = pi[q];
        if(a[q + 1] == b[i]) ++q;
    }
    return q;
}
inline bool pc(char a[], char b[], int pi[]){
    int q = 0;
    int n = strlen(b + 1), m = strlen(a + 1);
    for(int i = 1; i <= n ; ++i){
        while(a[q + 1] != b[i] && q)
            q = pi[q];
        if(a[q + 1] == b[i]) ++q;
        if(q == m) return 1;
    }
    return 0;
}
int main()
{
    freopen("adn.in", "r", stdin);
    freopen("adn.out", "w", stdout);
    scanf("%d", &n);
    for(int i = 0; i < n ; ++i){
        scanf("%s", s[i] + 1);
        ma(s[i], pi[i]);
        c[i] = strlen(s[i] + 1);
    }
    for(int i = 0; i < n ; ++i){
        for(int j = 0; j < n ; ++j){
            if(i == j || c[j] < c[i]) continue ;
            bool ok = pc(s[i], s[j], pi[i]);
            if(ok){
                for(int j = i; j < n - 1 ; ++j){
                    strcpy(s[j] + 1, s[j + 1] + 1);
                    c[j] = c[j + 1];
                    memcpy(pi[j], pi[j + 1], sizeof(pi[j + 1]));
                }
                --n; --i;
                break ;
            }
        }
    }
    for(int i = 0; i < n ; ++i){
        for(int j = 0; j < n ; ++j){
            if(i == j) continue ;
            int l = gi(s[j], s[i], pi[j]);
            cost[i][j] = -l;
        }
    }
    memset(d, 0x3f, sizeof(d));
    for(int i = 0; i < n ; ++i)
        d[(1 << i)][i] = c[i];
    for(int mask = 0; mask < (1 << n) ; ++mask){
        for(int i = 0; i < n ; ++i){
            if(!((1 << i) & mask)) continue ;
            for(int j = 0; j < n ; ++j){
                if((1 << j) & mask) continue ;
                int mask2 = (1 << j) | mask;
                int C = d[mask][i] + cost[i][j] + c[j];
                if(C < d[mask2][j]){
                    d[mask2][j] = C;
                    TT[mask2][j] = i;
                }
            }
        }
    }
    int Min = 2000000000, w = 0, mask = (1 << n) - 1;
    for(int i = 0; i < n ; ++i)
        if(d[mask][i] < Min) Min = d[mask][i], w = i;

    while(mask){
        Sol.push_back(w);
        int aux = mask; mask = mask - (1 << w);
        w = TT[aux][w];
    }
    reverse(Sol.begin(), Sol.end());
    printf("%s", s[Sol[0]] + 1);
    int Last = -cost[Sol[0]][Sol[1]];
    for(int i = 1; i < Sol.size() ; ++i){
        printf("%s", s[Sol[i]] + Last + 1);
        if(i + 1 < Sol.size()) Last = -cost[Sol[i]][Sol[i + 1]];
    }
    return 0;
}