Cod sursa(job #848634)

Utilizator SebiSebiPirtoaca George Sebastian SebiSebi Data 5 ianuarie 2013 17:38:12
Problema ADN Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.11 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],d[NMAX][(1<<NMAX)+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,aux;
    for(i=1;i<=n;i++) {
		aux=n;
        for(j=1;j<=n;j++)
            if(i!=j) {
                if(KMP(c[j],c[i])) {
                    strcpy(c[i],c[n]);
					n--;
                    break;
                }
            }
		if(aux!=n)
			i--;
	}
}
 
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=1;i<=n;i++) {
        prefix(c[i],strlen(c[i]+1));
        for(j=1;j<=n;j++)
            if(i!=j) {
                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=6;s<=(1<<(n+1))-1;s++) {
        for(i=1;i<=n;i++)
            if(s-1==(1<<i))
                break;
        if(i<=n)
            continue;
        for(i=1;i<=n;i++)
            if(BIT(s,i)) {
                for(vector <muchie> :: iterator it=v[i].begin();it!=v[i].end();it++) 
                    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((1<<i)+1==s || i<=0) {
        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=1;i<=n;i++) {
        f>>(c[i]+1);
        c[i][0]=' ';
    }
    f.close();
    remove(n);
    if(n==1) {
        g<<c[1]+1;
        g<<'\n';
        g.close();
        return 0;
    }
    builtgraph(n);
    dp(n);
    cost=-1;
    s=(1<<(n+1))-1;
    for(i=1;i<=n;i++)
        if(d[i][s]>cost) {
            cost=d[i][s];
            x=i;
        }
    afisare(x,s);
    g<<'\n';
    g.close();
    return 0;
}