Cod sursa(job #203347)

Utilizator mihai_floreaFlorea Mihai Alexandru mihai_florea Data 15 august 2008 18:02:52
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.84 kb
#include <fstream>
#include <string>
using namespace std;
const int LMAX=30001;
int n,pi[LMAX],c[18][18],bad;
string s[18];

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

void read(){
     string aux;
     getline(f,aux);
     n=atoi(aux.c_str());
     for (int i=0;i<n;++i)
       getline(f,s[i]);
     }    
void prefix(string s){
     int i,x=0;
     memset(pi,0,sizeof(pi));
     for (i=1;i<s.size();++i){
         while (x>0 && s[x]!=s[i]) x=pi[x-1];
         if (s[x]==s[i]) x++;
         pi[i]=x;
         }
     } 
int kmp(string s,string t){
    //cel mai lung prefix al lui s care este sufix al lui t
     int i,x=0;
     for (i=0;i<t.size();++i){
         while (x>0 && s[x]!=t[i]) x=pi[x-1];
         if (s[x]==t[i]) x++;
         if (x==s.size()) return -1;
         }
     return x;
     }
void build(){
     int i,j;
     for (i=0;i<n;++i)
      for (j=0;j<n;++j)
       if (i!=j){
         prefix(s[j]);
         c[i][j]=kmp(s[j],s[i]);
         if (c[i][j]==-1) bad|=(1<<j);
         }
     }

int a[18][1<<18],urm[18][1<<18];
void solve(){
     int i,j,k,t;
     for (j=1;j<(1<<n);++j)
       for (i=0;i<n;++i)
        if (!((1<<i)&j)) {
          a[i][j]=-1;               
          for (k=0;k<n;++k)
           if ((1<<k)&j)
            if (a[k][j-(1<<k)]+c[i][k]>a[i][j]){ 
              a[i][j]=a[k][j-(1<<k)]+c[i][k];
              urm[i][j]=k;}
          }
     //aflam maximul    
     t=-1;j=(1<<n)-1-bad;
     for (i=0;i<n;++i)
      if (a[i][j-(1<<i)]>t){
        k=i;
        t=a[i][j-(1<<i)];}
     //reconstituim drumul
     t=j-(1<<k);
     g<<s[k];
     while (t>0){
           i=urm[k][t];
           for (j=c[k][i];j<s[i].size();++j) g<<s[i][j];
           t-=(1<<i);
           k=i;}
     }
int main(){
    read();
    build();
    solve();
    return 0;
}