Cod sursa(job #3345777)

Utilizator Victor5539Tanase Victor Victor5539 Data 11 martie 2026 08:21:21
Problema ADN Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.6 kb
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,unroll-loops,fast-math,O3")
#pragma GCC target("avx,avx2,fma")
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");

const int NMAX=18,PMAX=(1<<NMAX),MOD=1e9+7,BASE=27,LENMAX=3e4;
int n,i,j,h[NMAX+5][LENMAX+5],p[LENMAX+5],l[NMAX+5][NMAX+5],val[NMAX+5];
int mask,auxmask,lsb,nr,v[NMAX+5],bit1,bit2,final_mask,ans_mask,ans_last,ans_len=1e9;
string s[NMAX+5];
vector <int> sol;

struct elem{
int prev,len;}dp[PMAX+5][NMAX+2];

int longest_suffix(int i, int j)
{
    int hash1,hash2;
    for (int len=min(s[i].size(),s[j].size()); len>=1; len--)
    {
        hash2=h[j][len-1];
        hash1=h[i][s[i].size()-1];
        if (s[i].size()-len>0)
            hash1=(hash1-h[i][s[i].size()-1-len])%MOD;

        if (hash1<MOD)
            hash1+=MOD;

        hash2=1LL*hash2*p[s[i].size()-len]%MOD;

        if (hash1==hash2)
            return len;
    }

    return 0;
}

bool verif(int i, int j)
{
    if (s[i].size()>s[j].size())
        return false;

    int hash1,hash2;

    for (int k=0; k<=s[j].size()-s[i].size(); k++)
    {
        hash2=h[j][k+s[i].size()-1];
        if (k>0)
            hash2=(hash2-h[j][k-1])%MOD;

        if (hash2<0)
            hash2+=MOD;

        hash1=h[i][s[i].size()-1];
        hash1=1LL*hash1*p[k]%MOD;

        if (hash1==hash2)
            return true;
    }




    return false;
}


bool verif_mask(int mask)
{
    int val=(mask)&(mask-1);
    return val!=0;
}

void init(int mask ,int bit)
{
    if (dp[mask][bit].prev==0)
    {
        dp[mask][bit].prev=-1;
        dp[mask][bit].len=1e9;
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    fin.tie(nullptr); fout.tie(nullptr);

    fin>>n;
    for (i=1; i<=n; i++)
        fin>>s[i];

    p[0]=1;
    for (i=1; i<=LENMAX; i++)
        p[i]=1LL*BASE*p[i-1]%MOD;

    for (i=1; i<=n; i++)
    {
        for (j=0; j<s[i].size(); j++)
        {
            h[i][j]=1LL*p[j]*(s[i][j]-'A'+1)%MOD;
            if (j>0)
                h[i][j]=(h[i][j]+h[i][j-1])%MOD;
        }
    }

    for (i=1; i<=n; i++)
        for (j=1; j<=n; j++)
            l[i][j]=longest_suffix(i,j);

    for (i=1; i<=n; i++)
        for (j=1; j<=n; j++)
            if (verif(i,j))
                val[j-1]+=(1<<(i-1));

    for (i=0; i<n; i++)
    {
        dp[1<<i][i].len=s[i+1].size();
        dp[1<<i][i].prev=-1;
    }

    for (mask=1; mask<(1<<n); mask++)
    {
        if (verif_mask(mask))
        {
            auxmask=mask; nr=0; final_mask=0;

            while (auxmask)
            {
                lsb=(auxmask)&(-auxmask);
                v[++nr]=log2(lsb);
                auxmask-=lsb;
                final_mask|=val[v[nr]];
            }

            for (i=1; i<=nr; i++)
                for (j=i+1; j<=nr; j++)
                {
                    bit1=v[i]; bit2=v[j];
                    init(mask,bit1);
                    init(mask,bit2);

                    if (dp[mask][bit1].len>dp[mask-(1<<bit1)][bit2].len+s[bit1+1].size()-l[bit2+1][bit1+1])
                    {
                        dp[mask][bit1].len=dp[mask-(1<<bit1)][bit2].len+s[bit1+1].size()-l[bit2+1][bit1+1];
                        dp[mask][bit1].prev=bit2+1;
                    }

                    if (dp[mask][bit2].len>dp[mask-(1<<bit2)][bit1].len+s[bit2+1].size()-l[bit1+1][bit2+1])
                    {
                        dp[mask][bit2].len=dp[mask-(1<<bit2)][bit1].len+s[bit2+1].size()-l[bit1+1][bit2+1];
                        dp[mask][bit2].prev=bit1+1;
                    }
                }

            if (final_mask==(1<<n)-1)
            {
                for (i=1; i<=nr; i++)
                {
                    bit1=v[i];

                    if (dp[mask][bit1].len<ans_len)
                    {
                        ans_len=dp[mask][bit1].len;
                        ans_mask=mask;
                        ans_last=bit1;
                    }
                }
            }
        }
    }

    while (dp[ans_mask][ans_last].prev!=-1)
    {
        int new_mask,new_last;
        new_mask=ans_mask-(1<<(ans_last));
        new_last=dp[ans_mask][ans_last].prev-1;
        sol.push_back(ans_last+1);
        ans_last=new_last;
        ans_mask=new_mask;
    }

    sol.push_back(ans_last+1);

    reverse(sol.begin(),sol.end());

    fout<<s[sol[1]];
    for (i=1; i<sol.size(); i++)
    {
        int val=l[sol[i-1]][sol[i]];
        for (j=val; j<s[sol[i]].size(); j++)
            fout<<s[sol[i]][j];

    }

    return 0;
}