Cod sursa(job #2961948)

Utilizator armigheGheorghe Liviu Armand armighe Data 7 ianuarie 2023 14:27:32
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.2 kb
#include<bits/stdc++.h>
#define INF 2000000000
using namespace std;
ifstream f("adn.in");
ofstream g("adn.out");
struct elem
{
    int x,c;
};
vector<elem>a[20];
vector<int>v;
char s[20][30002];
int nu[20],lps[30002],cc[20][20];
int dp[262150][20];
bool kmp1(int p,int q)
{
    int n1,n2,x,i;
    n1=strlen(s[p]+1);
    n2=strlen(s[q]+1);
    for(i=0;i<=n1||i<=n2;i++)
        lps[i]=0;
    for(i=2;i<=n1;i++)
    {
        x=lps[i-1];
        while(x>0&&s[p][x+1]!=s[p][i])
            x=lps[x];
        if(s[p][x+1]==s[p][i])
            x++;
        lps[i]=x;
    }
    x=0;
    for(i=1;i<=n2;i++)
    {
        while(x>0&&s[p][x+1]!=s[q][i])
            x=lps[x];
        if(s[p][x+1]==s[q][i])
            x++;
        if(x==n1)
            return 0;
    }
    return 1;
}

int kmp2(int q,int p)
{
    int n1,n2,x,i;
    n1=strlen(s[p]+1);
    n2=strlen(s[q]+1);
    for(i=0;i<=n1||i<=n2;i++)
        lps[i]=0;
    for(i=2;i<=n1;i++)
    {
        x=lps[i-1];
        while(x>0&&s[p][x+1]!=s[p][i])
            x=lps[x];
        if(s[p][x+1]==s[p][i])
            x++;
        lps[i]=x;
    }
    x=0;
    for(i=1;i<=n2;i++)
    {
        while(x>0&&s[p][x+1]!=s[q][i])
            x=lps[x];
        if(s[p][x+1]==s[q][i])
            x++;
    }
    return x;
}

int main()
{
    int n,i,j,k,sol=0,x=0,p=1,l;
    f>>n;
    for(i=1;i<=n;i++)
        f>>(s[i]+1);
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    if(i!=j&&kmp1(i,j)==0)
        nu[i]=1;
    for(i=1;i<=n;i++)
        nu[i]+=nu[i-1];
    for(i=1;i<=n;i++)
    if(nu[i]==nu[i-1])
    for(j=1;j<=n;j++)
    if(nu[j]==nu[j-1])
    if(i!=j)
        cc[i][j]=kmp2(i,j),a[i].push_back({j,cc[i][j]});
    for(i=1;i<=n-nu[n];i++)
        p*=2;
    p--;
    for(i=0;i<=p;i++)
    for(j=0;j<=n;j++)
        dp[i][j]=-INF;
    for(i=1;i<=n;i++)
    if(nu[i]==nu[i-1])
        dp[(1<<(i-nu[i]-1))][i]=0;
    for(i=0;i<p;i++)
    for(j=1;j<=n;j++)
    if(nu[j]==nu[j-1])
    if(dp[i][j]!=-INF)
    {
        l=a[j].size();
        for(k=0;k<l;k++)
        if((i&(1<<(a[j][k].x-nu[a[j][k].x]-1)))==0)
            dp[i|(1<<(a[j][k].x-nu[a[j][k].x]-1))][a[j][k].x]=max(dp[i|(1<<(a[j][k].x-nu[a[j][k].x]-1))][a[j][k].x],dp[i][j]+a[j][k].c);//cout<<i<<" "<<j<<" "<<dp[i][j]<<" "<<(i|(1<<(a[j][k].x-nu[a[j][k].x]-1)))<<" "<<a[j][k].x<<" "<< dp[i|(1<<(a[j][k].x-nu[a[j][k].x]-1))][a[j][k].x]<<'\n';
    }
    for(i=1;i<=n;i++)
    if(nu[i]==nu[i-1])
    {
        if(dp[p][i]>sol)
            sol=dp[p][i],x=i;
    }
    v.push_back(x);
    while(__builtin_popcount(p)!=1)
    {
        for(auto y:a[x])
        if(((p&(1<<(x-nu[x]-1)))!=0)&&dp[(p^(1<<(x-nu[x]-1)))][y.x]==dp[p][x]-cc[y.x][x])
        {
            p=(p^(1<<(x-nu[x]-1))),x=y.x;
            break;
        }
        v.push_back(x);
    }
    reverse(v.begin(),v.end());
    l=strlen(s[v[0]]+1);
    for(j=1;j<=l;j++)
        g<<s[v[0]][j];
    for(i=1;i<(int)v.size()-1;i++)
    {
        l=strlen(s[v[i]]+1);
        for(j=cc[v[i-1]][v[i]]+1;j<=l;j++)
            g<<s[v[i]][j];
    }
    l=strlen(s[v[v.size()-1]]+1);
    for(j=cc[v[v.size()-2]][v[v.size()-1]]+1;j<=l;j++)
        g<<s[v[v.size()-1]][j];
    return 0;
}