Cod sursa(job #210678)

Utilizator Pepelea_FlaviuFlaviu Pepelea Pepelea_Flaviu Data 28 septembrie 2008 16:44:58
Problema ADN Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.16 kb
# include <cstdio>
# include <string.h>

# define FIN "adn.in"
# define FOUT "adn.out"
# define MAXN 20
# define MAXL 30005
# define MAXM (1<<18)+5

int N,i,j,Nod = 0,maxq;
int mx,prev,lant,t;
int Prefix[MAXL];
int C[MAXN][MAXN];
int D[MAXN][MAXM];
int P[MAXN][MAXM];
char s[MAXN][MAXL];
unsigned char d[MAXN];

    void prefix(int p)
    {
        int i,L,k;
        
        L = strlen(s[p]+1);
        Prefix[1] = k = 0;
        for (i = 2; i <= L; ++i)
          {
             while (k && s[p][k+1] != s[p][i])
               k = Prefix[k];
             if (s[p][k+1] == s[p][i])
               k++;
             Prefix[i] = k;
          }
    }
    
    int KMP(int p, int r)
    {
        int i,k,l,L;
        
        l = strlen(s[p]+1);
        L = strlen(s[r]+1);
        k = 0;
        for (i = 1; i <= l; ++i)
          {
             while (k && s[r][k+1] != s[p][i])
               k = Prefix[k];
             if (s[r][k+1] == s[p][i])
               k++;
             if (k == L && l != L) return -1;
          }
        return k;
    }
    
    void delete_duplicate()
    {
        int i,j,ok;
        for (i = 1; i <= N; ++i)
          {
             prefix(i);
             ok = 0;
             for (j = 1; j <= N; ++j)
               if (i != j && KMP(j,i) != -1)
                 ok++;
             if (ok == N-1) d[++Nod] = i;
          }
    }
    
    void common()
    {
        int i,j;
        for (i = 1; i <= Nod; ++i)
          for (j = 1; j <= Nod; ++j)
            if (i != j)
              C[i][j] = KMP(d[i],d[j]);
            else
              C[i][j] = -1;
    }
    
    void dinamic()
    {
        int i,j,k;
        
        maxq = 1 << Nod;
        for (i = 1; i < maxq; ++i)
          for (j = 1; j <= Nod; ++j)
            {
              D[j][i] = -1;
              if (i == 1 << (j-1)) D[j][i] = 0;
                else
                  {
                     for (k = 1; k <= Nod; ++k)
                       if (k != j && (i & (1 << (k-1))))
                         if (D[k][i-(1<<(j-1))]+C[j][k]>D[j][i])
                           {
                              D[j][i] = D[k][i-(1<<(j-1))]+C[j][k];
                              P[j][i] = k;
                           }
                  }
            }
        mx = -1;     
        for (i = 1; i <= Nod; ++i)
          if (mx < D[i][maxq-1]) 
            {
               mx = D[i][maxq-1];
               prev = i;
            }
        lant = maxq-1; t = 0;
        
        while (lant)
          {
             k = C[t][prev];
             j = strlen(s[d[prev]]+1);
             for (i = k+1; i <= j; ++i)
               printf("%c",s[d[prev]][i]);
             t = prev;
             prev = P[prev][lant];
             lant = lant - (1 << (t - 1));
          }
        
    }

    int main()
    {
        freopen(FIN,"r",stdin);
        freopen(FOUT,"w",stdout);
        
        scanf("%d\n",&N);
        for (i = 1; i <= N; ++i)
          gets(s[i]+1);
          
        delete_duplicate();
        
        common();
        
        dinamic();
        
        return 0;
    }