Cod sursa(job #2740397)

Utilizator hhhhhhhAndrei Boaca hhhhhhh Data 12 aprilie 2021 20:32:55
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.83 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
typedef unsigned long long ull;
typedef long long ll;
int n;
vector<string> s,aux;
ull h[51][30005],pw[30005];
const ull baza=5;
string ans;
vector<int> muchii[51];
string lft[51];
bool use[51];
ll cost[51][51];
int dp[270005][21],from[270005][21];
bool comp(string a, string b)
{
    if(a.size()!=b.size())
        return a.size()<b.size();
    return a<b;
}
ull toint(char c)
{
    if(c=='A')
        return 1;
    if(c=='C')
        return 2;
    if(c=='G')
        return 3;
    if(c=='T')
        return 4;
}
bool common(int i, int j)
{
    int lgi=s[i].size();
    int lgj=s[j].size();
    for(int dr=lgi-1;dr<lgj;dr++)
    {
        ull hs=h[j][dr];
        ll st=dr-lgi;
        if(st>=0)
            hs-=h[j][st]*pw[lgi];
        if(hs==h[i][lgi-1])
            return 1;
    }
    return 0;
}
string getpref(int i, int j)
{
    string ans;
    int maxi=0;
    for(int dr=0;dr<s[j].size();dr++)
    {
        ull hj=h[j][dr];
        ull st=s[i].size()-1-dr;
        if(st<0)
            break;
        ull hi=h[i][s[i].size()-1];
        if(st>0)
            hi-=h[i][st-1]*pw[dr+1];
        if(hi==hj)
            maxi=dr+1;
    }
    ans=s[j].substr(0,maxi);
    return ans;
}
int main()
{
    fin>>n;
    pw[0]=1;
    for(int i=1;i<=30000;i++)
        pw[i]=pw[i-1]*baza;
    for(int i=1;i<=n;i++)
    {
        string a;
        fin>>a;
        s.push_back(a);
    }
    sort(s.begin(),s.end());
    s.erase(unique(s.begin(),s.end()),s.end());
    sort(s.begin(),s.end(),comp);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<s[i].size();j++)
        {
            if(j==0)
                h[i][j]=toint(s[i][j]);
            else
                h[i][j]=h[i][j-1]*baza+toint(s[i][j]);
        }
        for(int j=i-1;j>=0;j--)
            if(common(j,i))
                use[j]=1;
    }
    for(int i=0;i<n;i++)
        if(!use[i])
            aux.push_back(s[i]);
    s=aux;
    aux.clear();
    int suma=0;
    for(int i=0;i<s.size();i++)
        for(int j=0;j<s[i].size();j++)
        {
            if(j==0)
                h[i][j]=toint(s[i][j]);
            else
                h[i][j]=h[i][j-1]*baza+toint(s[i][j]);
        }
    for(int i=0;i<s.size();i++)
    {
        suma+=s[i].size();
        for(int j=0;j<s.size();j++)
            if(i!=j)
                cost[i][j]=getpref(i,j).size();
    }
    int lg=s.size();
    for(int mask=0;mask<(1<<lg);mask++)
    {
        int nrbit=0;
        for(int bit=0;bit<lg;bit++)
            if((mask>>bit)&1)
                nrbit++;
        if(nrbit==1)
            continue;
        for(int i=0;i<lg;i++)
            if((mask>>i)&1)
                for(int j=0;j<lg;j++)
                    if(i!=j)
                        if((mask>>j)&1)
                            if(dp[mask][i]<=dp[mask-(1<<i)][j]+cost[j][i])
                            {
                                dp[mask][i]=dp[mask-(1<<i)][j]+cost[j][i];
                                from[mask][i]=j;
                            }
    }
    int maxim=-1,last;
    for(int i=0;i<lg;i++)
        if(dp[(1<<lg)-1][i]>maxim)
        {
            maxim=dp[(1<<lg)-1][i];
            last=i;
        }
    vector<int> order;
    order.push_back(last);
    int mask=(1<<lg)-1;
    while(mask>0)
    {
        int plsno=last;
        last=from[mask][last];
        mask-=(1<<plsno);
        if(mask!=0)
            order.push_back(last);
    }
    reverse(order.begin(),order.end());
    ans+=s[order[0]];
    for(int i=1;i<order.size();i++)
    {
        int cur=order[i],prv=order[i-1];
        int sz=getpref(prv,cur).size();
        string add=s[cur].substr(sz);
        ans+=add;
    }
    fout<<ans;
    return 0;
}