Cod sursa(job #2764789)

Utilizator OvidRata Ovidiu Ovid Data 22 iulie 2021 17:16:09
Problema ADN Scor 50
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.91 kb
#include<bits/stdc++.h>
using namespace std;
#define INIT  ios_base :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define mp make_pair
#define pb push_back
#define ft first
#define sc second
#define ll long long
#define pii pair<int, int>
#define count_bits __builtin_popcount
//#define int ll

ifstream fin("adn.in"); ofstream fout("adn.out");

#define cin fin
#define cout fout


int N;
vector<string> v2, v;


//returns true if s2 is part of s1
int p[60003+10];
bool kmp(string &s1, string &s2, int p[]){
int n=s1.length(), m=s2.length();
bool ans=false;
p[0]=p[1]=0;
for(int i=2; i<=m; i++){
    p[i]=p[i-1];
    while( (p[i]>0) && (s2[p[i] ]!=s2[i-1]) ){
        //p[i]=p[p[i] ]
        p[i]=p[p[i]];
    }
    if(s2[p[i] ]==s2[i-1]){
        p[i]++;
    }
}

p[m+1]=0;

for(int i=1; i<=n; i++){
    int j=i+m+1;
    p[j]=p[j-1];
    while( (p[j]>0) && (s2[p[j] ]!=s1[i-1]) ){
        p[j]=p[p[j] ];
    }
    if(s2[p[j] ]==s1[i-1] ){
        p[j]++;
    }
    if(p[j]==((int)s2.size()) ){ans=true;}
}

if(s1.length()==s2.length()){
    ans=false;
}

return ans;

}





void eliminate(vector<string> v1, vector<string> &v2){

for(int i=0; i<v1.size(); i++){
    bool is_prt=false;
    for(int j=0; j<v1.size(); j++){
        if(i==j){continue;}
        is_prt|=kmp(v1[i], v1[j], p);
    }
    if(!is_prt){
        v2.pb(v1[i]);
    }
}
    N=v2.size();


}






//building the graph
//{u, w}
int g[20][20];

void build(vector<string> &v){
    for(int i=0; i<v.size(); i++){
        for(int j=0; j<v.size(); j++){
            if(i==j){continue;}
            kmp(v[i], v[j], p);
            g[i][j]=((int)v[j].length())-p[ (((int)v[j].length())+((int)v[i].length()) )+1 ];
        }
    }
}



//getting the ham-path/ maintain the seq
int dp[ (1ll<<18)-1 ][18];
pii anc[(1ll<<18)-1 ][18];


void build_dp(vector<string> &v){
    N=v.size();
    for(int i=0; i<N; i++){
        dp[1ll<<i][i]=v[i].length();
        anc[1ll<<i][i]={0, 0};
    }

    for(int b=1; b<(1ll<<N); b++){
        for(int i=0; i<N; i++){
            if( (b&(1ll<<i))>0 ){
                if(dp[b][i]>0){

                    for(int j=0; j<N; j++){
                        //if(i==j){continue;}
                        if(  (b&(1ll<<j))>0 ){continue;}
                        if(dp[b|(1ll<<j) ][j]==0){
                            dp[b|(1ll<<j) ][j]=dp[b][i]+g[i][j];
                            anc[b|(1ll<<j) ][j]={b, i};
                        }
                        else{
                            if( (dp[b][i]+g[i][j] )<dp[b|(1ll<<j) ][j] ){
                                dp[b|(1ll<<j) ][j]=(dp[b][i]+g[i][j] );
                                anc[b|(1ll<<j) ][j]={b, i};
                            }
                        }
                    }

                }
            }
        }
    }

}



void build_ans(){

int mn=1e9;
pii pr={0, 0};

for(int i=0; i<N; i++){
    if(dp[(1ll<<N)-1][i]<mn){
        mn=dp[(1ll<<N)-1][i];
        pr={ (1ll<<N)-1, i};
    }
}
vector<int> ind;
while(pr!=mp(0,0) ){
    ind.pb(pr.sc);
    pr=anc[pr.ft ][pr.sc];
}

reverse(ind.begin(), ind.end());
cout<<v[ind[0] ];
//cout<<ind.size();
//cout<<ind[0]<<" ";
for(int i=1; i<ind.size(); i++){
    //cout<<ind[i]<<" ";
 for(int j= (((int)v[ind[i] ].length())-1-g[ind[i-1] ][ind[i] ]+1); j<v[ind[i] ].length(); j++ ){
    cout<<v[ind[i] ][j];
 }
}



}



int32_t main(){
INIT

//test
/*
string s2="abcd", s1="abaabeabcd";
int p[40]; memset(p, 0, sizeof(p));
kmp(s1, s2, p);
for(int i=1; i<=s1.size(); i++){
    int j=i+1+((int)s2.size());
    cout<<p[j]<<" ";
}
*/


cin>>N;
for(int i=1; i<=N; i++){
    string S;
    cin>>S;
    v2.pb(S);
}
eliminate(v2, v);
//cout<<v.size()<<"\n";
build(v);
build_dp(v);
build_ans();


return 0;
}