Cod sursa(job #848599)

Utilizator SebiSebiPirtoaca George Sebastian SebiSebi Data 5 ianuarie 2013 17:15:00
Problema ADN Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.41 kb
#include<iostream>
#include<fstream>
#include<vector>
#include<string.h>
using namespace std;
 
#define NMAX 19
#define LMAX 30005
 
ofstream g("adn.out");
 
struct muchie {
    int cost,y;
};
 
vector <muchie> v[NMAX];
int l[LMAX],r[NMAX],d[NMAX][(1<<(NMAX-1))+1],nod[NMAX][(1<<NMAX)+1],a[NMAX][NMAX];
char c[NMAX][LMAX];
 
inline void prefix(char s[], int n)
{
    int i,k;
    l[1]=0;
    for(i=2;i<=n;i++) {
        k=l[i-1];
        while(k && s[k+1]!=s[i])
            k--;
        if(s[k+1]==s[i])
            k++;
        l[i]=k;
    }
}
 
inline int KMP(char s[], char  p[])
{
    int i,k,n,m;
    n=strlen(s+1);
    m=strlen(p+1);
    prefix(p,m);
    k=0;
    for(i=1;i<=n;i++) {
        while(k && p[k+1]!=s[i])
            k=l[k];
        if(p[k+1]==s[i])
            k++;
        if(k==m) 
            return 1;
    }
    return 0;
}
 
inline void remove(int n)
{
    int i,j;
    for(i=0;i<=n-1;i++)
        for(j=0;j<=n-1;j++)
            if(r[j]==0 && i!=j) {
                if(KMP(c[j],c[i])) {
                    r[i]=1;
                    break;
                }
            }
}
 
inline int KMP2(char s[], char p[])
{
    int i,k,n,m;
    n=strlen(s+1);
    m=strlen(p+1);
    k=0;
    for(i=1;i<=n;i++) {
        while(k && s[i]!=p[k+1])
            k=l[k];
        if(s[i]==p[k+1])
            k++;
    }
    return k;
}
 
inline void builtgraph(int n)
{
    int i,j;
    muchie x;
    for(i=0;i<=n-1;i++) {
        if(r[i]==1)
            continue;
        prefix(c[i],strlen(c[i]+1));
        for(j=0;j<=n-1;j++)
            if(i!=j && r[j]==0) {
                x.y=j;
                x.cost=KMP2(c[j],c[i]);
                v[i].push_back(x);
                a[i][j]=x.cost;
            }
    }
}
 
inline int BIT(int nr, int i)
{
    return (nr & (1<<i))!=0;
}
 
inline void dp(int n)
{
    int i,s;
    for(s=3;s<=(1<<n)-1;s++) {
        for(i=0;i<=n-1;i++)
            if(s==(1<<i))
                break;
        if(i<=n-1)
            continue;
        for(i=0;i<=n-1;i++)
            if(r[i]==0 && BIT(s,i)) {
                for(vector <muchie> :: iterator it=v[i].begin();it!=v[i].end();it++) {
                    if(s-(1<<it->y)<0)
                        continue;
                    if(d[i][s]<=d[it->y][s-(1<<i)]+it->cost && BIT(s-(1<<i),it->y)) {
                        d[i][s]=d[it->y][s-(1<<i)]+it->cost;
                        nod[i][s]=it->y;
                    }
                }
            }
    }
}
 
inline void afisare(int i, int s)
{
    if(nod[i][s]==-1) {
        g<<c[i]+1;
        return;
    }
    int x;
    x=nod[i][s];
    afisare(x,s-(1<<i));
    g<<c[i]+a[i][x]+1;
}

int main ()
{
    int i,n,cost,x,s;
    ifstream f("adn.in");
    f>>n;
    for(i=0;i<=n-1;i++) {
        f>>(c[i]+1);
        c[i][0]=' ';
    }
    f.close();
    remove(n);
    x=0;
    for(i=0;i<=n-1;i++)
        if(r[i]==0)
            x++;
    if(x==1) {
        for(i=0;i<=n-1;i++)
            if(r[i]==0)
                break;
        g<<c[i]+1;
        g<<'\n';
        g.close();
        return 0;
    }
	memset(nod,-1,sizeof(nod));
    builtgraph(n);
    dp(n);
    cost=-1;
    s=(1<<n)-1;
    for(i=0;i<=n-1;i++)
        if(r[i]==0 && d[i][s]>cost) {
            cost=d[i][s];
            x=i;
        }
    afisare(x,s);
    g<<'\n';
    g.close();
    return 0;
}