Cod sursa(job #2962781)

Utilizator alex_bb8Banilean Alexandru-Ioan alex_bb8 Data 9 ianuarie 2023 14:40:04
Problema ADN Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.79 kb
#include <bits/stdc++.h>

using namespace std;

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

const int NMAX = 18;
const int LMAX = 30001;

int N;
vector<string> words;
vector<vector<int>> cost, dp, prevs;

void read(){
    
    cin >> N;
    
    words.resize(N);
    
    for(int i = 0; i < N; ++i)
        cin >> words[i];
    
}

vector<int> GetPi(string& s){
    
    int len = s.size();
    
    vector<int> pi(len + 1, -1);
    
    for(int i = 0; i < len; ++i){
        
        int j = pi[i];
        
        while(j != -1 && s[i] != s[j])
            j = pi[j];
        
        pi[i + 1] = j + 1;
    }
    
    return pi;
}


vector<string> preprocess(vector<string>& words){
    
    vector<string> aux;
    
    for(int i = 0; i < N; ++i){
        
        auto pi = GetPi(words[i]);
        bool matched = false;
        
        for(int j = 0; j < N; ++j){
            
            // KMP
            
            if(i == j) 
                continue;
            
            int index = 0;
                
            for(int k = 0; words[j][k] != NULL; ++k){
                
                while(index != -1 && words[j][k] != words[i][index])
                    index = pi[index];
                
                ++index;
                    
                if(index == words[i].size()){
                    matched = true;
                    break;
                }
            }
            
            if(matched) 
                break;
        }
        
        if(!matched)
            aux.push_back(words[i]);
    }
    
    return aux;
}

int GetCost(string a, string b){
    auto pi = GetPi(b);
    
    int index = 0;
    
    for(auto x : a){
        while(index != -1 && b[index] != x)
            index = pi[index];
        
        index += 1;
    }
    
    return index;
}

void solve(){
    
    vector<string> str = preprocess(words);
    
    N = str.size();
    
    cost.assign(N + 1, vector<int>(N + 1, -1));
    
    for(int i = 0; i < N; ++i)
        for(int j = 0; j < N; ++j)
            if(i != j)
                cost[i][j] = GetCost(str[i], str[j]);
    
    dp.assign(N + 2, vector<int>((1 << N) + 2, 0));
    prevs.assign(N + 2, vector<int>((1 << N) + 2, 0));
    
    for(int mask = 0; mask < (1 << N); ++mask){
        for(int i = 0; i < N; ++i){
            
            if(!(mask & (1 << i))) 
                continue;
            
            for(int j = 0; j < N; ++ j){
                
                if(i == j)
                    continue;
                    
                if(!(mask & (1 << j)))
                    continue;
                    
                int ct = dp[j][mask ^ (1 << i)] + cost[j][i];
                
                if(dp[i][mask] <= ct){
                    dp[i][mask] = ct;
                    prevs[i][mask] = j;
                }
            }    
        }
    }
    
    int node = 0;
    for(int i = 0; i < N; ++i)
        if(dp[node][(1 << N) - 1] < dp[i][(1 << N) - 1])
            node = i;
            
    vector<int> path;
    
    int mask = (1 << N) - 1;
    
    while(mask){
        path.push_back(node);
        
        int prev_mask = mask ^ (1 << node);
        int prev_node = prevs[node][mask];
        
        node = prev_node;
        mask = prev_mask;
    }
    
    reverse(path.begin(), path.end());
    
    int skip_next = 0;
    
    for(int i = 0; i < N ; ++i){
        int node = path[i];
        
        string s = str[node].substr(skip_next);
        
        cout << s;
        
        if(i != N - 1){
            skip_next = cost[node][path[i + 1]];
        }
        
    }
}

int main(){
    
    read();
    
    solve();

    return 0;
}