Cod sursa(job #1998955)

Utilizator refugiatBoni Daniel Stefan refugiat Data 9 iulie 2017 19:29:54
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.66 kb
#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int NMAX=18;
const int LMAX=30005;
ifstream si("adn.in");
ofstream so("adn.out");
int v[NMAX];

char s[NMAX][LMAX];
int lg[NMAX];
int pr[NMAX][LMAX];
int cost[NMAX][NMAX];
int d[1<<NMAX][NMAX];
bool util[NMAX];
int ant[1<<NMAX][NMAX];
vector<int> sol;
int main()
{
    int n;
    si>>n;
    for(int i=0;i<n;++i)
    {
        si>>s[i]+1;
        lg[i]=strlen(s[i]+1);
    }
    for(int i=0;i<n;++i)
    {
        int poz=0;
        pr[i][1]=0;
        for(int j=2;j<=lg[i];++j)
        {
            while(poz>0&&s[i][poz+1]!=s[i][j])
                poz=pr[i][poz];
            if(s[i][poz+1]==s[i][j])
                ++poz;
            pr[i][j]=poz;
        }
    }
    for(int i=0;i<n;++i)
    {
        if(util[i]==true)
            continue;
        for(int j=0;j<n;++j)
        {
            if(util[j]==true||j==i)
                continue;
            int poz=0;
            for(int k=2;k<=lg[i];++k)
            {
                while(poz>0&&s[j][poz+1]!=s[i][k])
                    poz=pr[j][poz];
                if(s[j][poz+1]==s[i][k])
                {
                    ++poz;
                }
                if(poz==lg[j])
                {
                    util[j]=true;
                    cost[i][j]=0;
                    break;
                }
            }
            cost[i][j]=lg[j]-poz;
        }
    }
    int m=0;
    for(int i=0;i<n;++i)
        if(util[i]==false)
        {
            v[m++]=i;
            //cout<<i;
        }
    int cmax=(1<<m)-1;

    for(int i=0;i<=cmax;++i)
        for(int j=0;j<m;++j)
            d[i][j]=INF;
    for(int i=0;i<m;++i)
        d[1<<i][i]=lg[v[i]];
    for(int i=1;i<=cmax;++i)
    {
        for(int j=0;j<m;++j)
        {
            if((i&(1<<j))==0)continue;
            for(int k=0;k<m;++k)
            {
                if(((1<<k)&i))continue;
                if(d[i+(1<<k)][k]>d[i][j]+cost[v[j]][v[k]])
                {
                    d[i+(1<<k)][k]=d[i][j]+cost[v[j]][v[k]];
                    ant[i+(1<<k)][k]=j;
                }
            }
        }
    }
    int ult=0;
    for(int i=0;i<m;++i)
    {
        if(d[cmax][ult]>d[cmax][i])
            ult=i;
    }
    for(int i=0;i<m;++i)
    {
        sol.push_back(v[ult]);
        int aux=ult;
        ult=ant[cmax][ult];
        cmax-=(1<<aux);
    }
    reverse(sol.begin(),sol.end());
    for(int i=0;i<sol.size();++i)
    {
        if(i==0)
            so<<s[sol[i]]+1;
        else
            so<<s[sol[i]]+1+(lg[sol[i]]-cost[sol[i-1]][sol[i]]);
    }
    return 0;
}