Cod sursa(job #733141)

Utilizator mihai995mihai995 mihai995 Data 11 aprilie 2012 15:48:34
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.34 kb
#include <fstream>
#include <cstring>
using namespace std;

const int N=20,M=1<<19,L=90005,inf=0x3f3f3f3f;
char s[N][L],aux[L];
int a[N][M],src[N][M],start[N][N],p[L],match[L],len[N],n;
bool inside[N][N];

ifstream in("adn.in");
ofstream out("adn.out");

int prefix(char a[],char b[])
{
    memset(p,0,sizeof(p));
    memset(aux,'\0',sizeof(aux));
    strcpy(aux+1,a+1);
    strcat(aux+1,"*");
    strcat(aux+1,b+1);
    p[0]=-1;
    for (int i=2;aux[i];i++)
        for (int j=p[i-1];j>=0;j=p[j])
            if (aux[j+1]==aux[i])
            {
                p[i]=j+1;
                break;
            }
    return p[strlen(aux+1)];
}

bool strmatch(char a[],char b[])
{
    memset(p,0,sizeof(p));
    memset(match,0,sizeof(match));
    p[0]=-1;
    for (int i=2;a[i];i++)
        for (int j=p[i-1];j>=0;j=p[j])
            if (a[j+1]==a[i])
            {
                p[i]=j+1;
                break;
            }
    int n=strlen(a+1);
    for (int i=1;b[i];i++)
        for (int j=match[i-1];j>=0;j=p[j])
            if (a[j+1]==b[i])
            {
                match[i]=j+1;
                if (match[i]==n)
                    return true;
                break;
            }
    return false;
}

inline void update(int& x,int val,int& src,int a)
{
    if (x<=val)
        return;
    x=val;
    src=a;
}

void print(int x,int key)
{
    if (key==1<<x)
    {
        out<<s[x]+1;
        return;
    }
    print(src[x][key],key ^ (1<<x));
    out<<(s[x]+len[x]-start[x][src[x][key]]+1);
}

int main()
{
    in>>n;
    for (int i=0;i<n;i++)
    {
        in>>(s[i]+1);
        len[i]=strlen(s[i]+1);
    }
    for (int i=0;i<n;i++)
        for (int j=0;j<n;j++)
        {
            if (strmatch(s[i],s[j]))
                continue;
            start[i][j]=len[i]-prefix(s[i],s[j]);
        }
    memset(a,inf,sizeof(a));
    for (int i=0;i<n;i++)
        a[i][1<<i]=len[i];
    for (int j=1;j<1<<n;j++)
        for (int i=0;i<n;i++)
            for (int k=0;k<n;k++)
                if ((j & (1<<i) ) && (j & (1<<k)) == 0)
                    update(a[k][j | (1<<k)],a[i][j] + start[k][i],src[k][j | (1<<k)],i);
    int key=(1<<n)-1,best=0;
    for (int i=0;i<n;i++)
        if (a[i][key]<a[best][key])
            best=i;
    print(best,key);
    out<<"\n";
    return 0;
}