Cod sursa(job #2801026)

Utilizator UnknownPercentageBuca Mihnea-Vicentiu UnknownPercentage Data 14 noiembrie 2021 18:33:40
Problema ADN Scor 20
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.43 kb
#include <bits/stdc++.h>

using namespace std;

inline void Open(const string Name) {
    #ifndef ONLINE_JUDGE
        (void)!freopen((Name + ".in").c_str(), "r", stdin);
        (void)!freopen((Name + ".out").c_str(), "w", stdout);
    #endif
}

const int INF = 1e9;

bitset <19> marked;

vector <array <int, 2>> Gr[19];

array <int, 2> path[1 << 19][19];

int dp[1 << 19][19], cost[19][10];
int pi[60005];

string v[19];

void printSTR(array <int, 2> cur) {
    if(cur[0] == 0)
        return;

    printSTR(path[cur[0]][cur[1]]);
    int wcost = cost[path[cur[0]][cur[1]][1]][cur[1]];
    if(path[cur[0]][cur[1]][0] == 0) 
        wcost = 0;

    cout << v[cur[1]].substr(wcost);
}

bool KMP(string st1, string st2) {
    char str1[30005], str2[30005];
    strcpy(str1, (' ' + st1).c_str());
    strcpy(str2, (' ' + st2).c_str());

    int len = strlen(str1) - 1, lenn = strlen(str2) - 1, q = 0;

    pi[1] = 0;
    for(int i = 2;i <= len;i++) {
        while(q && str1[q + 1] != str1[i]) 
            q = pi[q];
        if(str1[q + 1] == str1[i])
            q++;

        pi[i] = q;
    }

    q = 0;
    for(int i = 1;i <= lenn;i++)  {
        while(q && str1[q + 1] != str2[i])
            q = pi[q];
        if(str1[q + 1] == str2[i])
            q++;
        if(q == len)
            return 1;
    }
    return 0;
}


int LenPS(string str1, string str2) {
    string str = "2" + str2 + "2" +  str1;

    int len = str.size(), q = 0;

    pi[1] = 0;
    for(int i = 2;i < len;i++) {
        while(q && str[q + 1] != str[i])
            q = pi[q];
        if(str[q + 1] == str[i])
            q++;
        pi[i] = q; 
    }

    return pi[len - 1];
}

bool cmp(string str1, string str2) {
    return str1.size() < str2.size();
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    Open("adn");

    int N; cin >> N;
    for(int i = 0;i < N;i++)
        cin >> v[i];

    sort(v, v + N, cmp);

    for(int i = 0;i < N - 1;i++)
        for(int j = i + 1;j < N;j++)
            if(KMP(v[i], v[j]) == 1) {
                marked[i] = 1;
                break;
            }

    int cnt = 0;
    for(int i = 0;i < N;i++) {
        if(!marked[i]) {
            v[cnt++] = v[i];
        }
    }

    N = cnt;
    for(int i = 0;i < N;i++)
        for(int j = 0;j < N;j++)  
            if(i != j) {
                int val = LenPS(v[i], v[j]);
                Gr[j].push_back({i, val});
                cost[i][j] = val;
            }

    int limit = 1 << N;

    for(int i = 0;i < limit;i++)
        for(int j = 0;j < N;j++)
            dp[i][j] = -INF;

    for(int i = 0;i < N;i++)
        dp[1 << i][i] = 0;

    for(int i = 0;i < limit;i++)
        for(int j = 0;j < limit;j++) {
            if((i & (1 << j)) == 0)
                continue;

            for(array <int, 2> it : Gr[j]) {
                if((i & (1 << it[0])) == 0)
                    continue;

                if(dp[i ^ (1 << j)][it[0]] + it[1] > dp[i][j]) {
                    dp[i][j] = dp[i ^ (1 << j)][it[0]] + it[1];
                    path[i][j] = {i ^ (1 << j), it[0]};
                }

            }
        }

    int ans = -INF;
    array <int, 2> ppp;

    for(int i = 0;i < N;i++){
        if(dp[limit - 1][i] > ans) {
            ans = dp[limit - 1][i];
            ppp = {limit - 1, i};
        }
    }

    printSTR(ppp);

    return 0;
}