Cod sursa(job #1464307)

Utilizator t.g.g.tt.g.g.t t.g.g.t Data 22 iulie 2015 22:55:48
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.87 kb
#include <stdio.h>
#include <cstring>

char s[19][30005];
int lungime[20];


char sir[60005];
int z[60005];
int l;
int eliminat[20];


int cost[20][20];

int sol[20][300005];
int drum[20][300005];
int put[20];

int main()
{
    freopen("adn.in","r",stdin);
    freopen("adn.out","w",stdout);

    int n;
    scanf("%d\n",&n);

    for (int i=1; i<=n; ++i)
    {
        gets(s[i]);
        lungime[i] = strlen(s[i]);
    }

    for (int i=1; i<=n; ++i)
    {
        for (int j=1; j<=n; ++j)
        {
            if(i!=j)
            {
                l = lungime[i] + lungime[j] + 1;

                for (int ind=0; ind<lungime[i]; ++ind)
                {
                    sir[ind] = s[i][ind];
                    z[ind] = 0;
                }

                sir[lungime[i]] = '#';

                for (int ind=0; ind<lungime[j]; ++ind)
                {
                    sir[ind+lungime[i] + 1] = s[j][ind];
                    z[ind+lungime[i] + 1] = 0;
                }

                int st=0,dr=0;
                for (int ind=1; ind<l; ++ind)
                {
                    if(ind > dr)
                    {
                        st = ind; dr = ind;
                        while (dr<l && sir[dr] == sir[dr-st]) ++dr;
                        z[ind]=dr-st;
                        --dr;
                    }else
                    {
                        if (z[ind-st] < dr-ind+1)
                        {
                            z[ind] = z[ind-st];
                        }else
                        {
                            st=ind;
                            while (dr<l && sir[dr] == sir[dr-ind]) ++dr;
                            z[ind] = dr - st;
                            --dr;
                        }
                    }

                    if (ind>lungime[i])
                    if (z[ind] == lungime[i])
                    {
                        if (eliminat[i]==0) ++eliminat[0];
                        eliminat[i]=1;
                    }else
                    {
                        if (ind+z[ind] == l && cost[j][i]<z[ind]) { cost[j][i]=z[ind]; }
                    }
                }
            }

        }
    }

    put[1] = 1;
    for (int i=2; i<=n; ++i)
    {
        put[i] = put[i-1]*2;
    }

    int val=1<<(n-eliminat[0]);
    int stare[20]; for (int i=0; i<20; ++i) stare[i]=0;
    while (val > 0)
    {
        int i=1; while (stare[i] == 1 || (stare[i]==0 && eliminat[i]==1)) {stare[i]=0; ++i; } stare[i]=1;

        int nr = 0;
        for (int i=1; i<=n; ++i)
        {
            nr += put[i]*stare[i];
        }

        for (int i=1; i<=n; ++i)
        {
            if (stare[i] == 1)
            {
                stare[i]=0;
                nr-=put[i];
                for (int j=1; j<=n; ++j)
                {
                    if (stare[j]==1)
                    {
                        int nr2 = nr-put[j];
                        if (cost[i][j]+sol[j][nr2] > sol[i][nr]) { sol[i][nr] = cost[i][j]+sol[j][nr2]; drum[i][nr]=j; }
                    }
                }

                nr+=put[i];
                stare[i]=1;
            }
        }

        --val;
    }

    int nr = 0; for (int i=1; i<=n; ++i) { if (eliminat[i]==0) nr+=put[i]; }
    int maxim=-1;
    int care=0;
    for (int i=1; i<=n;++i)
    {
        if (eliminat[i]==0) if (sol[i][nr-put[i]]>maxim) { maxim=sol[i][nr-put[i]]; care=i;}
    }

    if (care==0) { maxim=-1; for (int i=1; i<=n; ++i) { if (maxim<lungime[i]) { maxim=lungime[i]; care=i; } } }
    nr-=put[care];
    printf("%s",s[care]);
    while (nr > 0)
    {
        int nou = drum[care][nr];
        printf("%s",(char*)(s[nou]+cost[care][nou]));
        care = nou;
        nr-=put[care];
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}