Cod sursa(job #3327191)

Utilizator Dia3141Costea Diana Stefania Dia3141 Data 2 decembrie 2025 18:29:12
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.58 kb
#include <fstream>
#include <cstring>
#define nmax 19
#define dim 30001
#define inf 1e9
using namespace std;
ifstream cin("adn.in");
ofstream cout("adn.out");
int n,lps[2*dim],cost[nmax][nmax],dp[nmax][(1<<nmax)],t[nmax][(1<<nmax)];
bool in[nmax];
string s[nmax];
void get_lps(string s){
    int len=0,i=1,n=s.size();
    while(i<n){
        if(s[i]==s[len]){
            len++;
            lps[i++]=len;
        }else if(len==0)
            lps[i++]=0;
        else
            len=lps[len-1];
    }
}
bool verif(int k1,int k2){
    int len=0,i=0,n=s[k1].size(),m=s[k2].size();
    if(n>m)
        return 0;
    while(i<m){
        if(s[k1][len]==s[k2][i]){
            len++;
            i++;
        }else if(len==0)
            i++;
        else
            len=lps[len-1];
        if(len==n)
            return 1;
    }
    return 0;
}
void new_words(){
    int k=0;
    for(int i=1;i<=n;i++)
        if(in[i])
            s[++k]=s[i];
    n=k;
}
void rec(int nod,int mask){
    int start=0;
    if(t[nod][mask]!=0){
        rec(t[nod][mask],mask-(1<<(nod-1)));
        start=cost[t[nod][mask]][nod];
    }
    for(int i=start;s[nod][i]!=0;i++)
        cout<<s[nod][i];
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s[i];
        in[i]=1;
    }
    for(int i=1;i<=n;i++)
        if(in[i]){
            get_lps(s[i]);
            for(int j=1;j<=n;j++)
                if(i!=j&&in[j]&&verif(i,j)){
                    in[i]=0;
                    break;
                }
        }
    new_words();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            if(i!=j){
                get_lps(s[i]+s[j]);
                cost[j][i]=lps[s[i].size()+s[j].size()-1];
            }
    }
    for(int mask=1;mask<(1<<n);mask++)
        for(int i=0;i<n;i++)
            dp[i+1][mask]=inf;
    for(int i=0;i<n;i++)
        dp[i+1][(1<<i)]=s[i+1].size();
    for(int mask=1;mask<(1<<n);mask++){
        for(int i=0;i<n;i++)
            if((mask>>i)&1){
                for(int j=0;j<n;j++)
                    if(i!=j&&!((mask>>j)&1)){
                        int next=mask+(1<<j);
                        if(dp[j+1][next]>dp[i+1][mask]+s[j+1].size()-cost[i+1][j+1]){
                            dp[j+1][next]=dp[i+1][mask]+s[j+1].size()-cost[i+1][j+1];
                            t[j+1][next]=i+1;
                        }
                    }
            }
    }
    int last=1;
    for(int i=2;i<=n;i++)
        if(dp[last][(1<<n)-1]>dp[i][(1<<n)-1])
            last=i;
    rec(last,(1<<n)-1);
    return 0;
}