Cod sursa(job #132279)

Utilizator vlad_popaVlad Popa vlad_popa Data 5 februarie 2008 15:51:37
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.82 kb
#include <cstdio>
#include <string>

using namespace std;

#define NMAX 18

string S[NMAX], sol;
int N;
int Pi[NMAX][1<<15];
int A[NMAX][NMAX];
int d[NMAX][1<<18];
int pred[NMAX][1<<18];
char sir[1<<15];

void read ()
{
    scanf ("%d\n", &N);
    
    int i;
    for (i = 0; i < N; ++ i)
    {
        gets (sir);
        S[i] = sir;
        S[i] = " " + S[i];
    }        
}

void Prefix (int p, int len)
{
    int k = 0, i;
    
    for (i = 2; i <= len; ++ i)
    {
        while (k > 0 && S[p][k + 1] != S[p][i])
            k = Pi[p][k];

        if (S[p][k + 1] == S[p][i])
            ++ k;
        Pi[p][i] = k;
    }
}

int KMP (int p1, int p2, int len)
{
    int q = 0, maxim = 0, i;
    for (i = 1; i <= len; ++ i)
    {
        while (q > 0 && S[p1][q + 1] != S[p2][i])
            q = Pi[p1][q];

        if (S[p1][q + 1] == S[p2][i])
            ++ q;
        
        if (maxim < q)
            maxim = q;
    }
    
    return maxim;    
}

int Get_Cost (int i, int mask)
{
    mask -= (1 << i);
    if (d[i][mask])
        return d[i][mask];
        
    if (!mask)
        return 0;
        
    int j, tmp, maxim = 0, p = 0;    
    for (j = 0; j < N; ++ j)
        if (mask & (1 << j) && A[j][i] != -1)
        {
            tmp = Get_Cost (j, mask) + A[j][i];
            if (maxim < tmp)
            {
                maxim = tmp;
                p = j;
            }
        }
    
    pred[i][mask] = p;    
    return d[i][mask] = maxim;
}

void Remake (int i, int mask)
{
    mask -= (1<<i);
    if (mask == 0)
        return;
        
    int p = pred[i][mask];
    sol += S[i].substr(1, S[i].length()-1-A[p][i]);
    //printf ("%s\n", sol.c_str());
    
    Remake (p, mask);
}

void solve ()
{
    int i, j;
    
    for (i = 0; i < N; ++ i)
        Prefix (i, S[i].length()-1);
        
    for (i = 0; i < N; ++ i)
        for (j = 0; j < N; ++ j)
            if (KMP (i, j, S[j].length()-1) == (S[i].length()-1) && i != j)
                S[i] = "";
    
    for (i = 0; i < N; ++ i)
        for (j = 0; j < N; ++ j)
            if (S[j] != "" && S[i] != "")
                A[i][j] = KMP (i, j, S[j].length()-1);
            else
                A[i][j] = -1;
            
    int maxim = 0, nod, tmp;
    for (i = 0; i < N; ++ i)
        if (S[i] != "")
        {
            tmp = Get_Cost (i, (1<<N) - 1);
            if (tmp > maxim)
            {
                maxim = tmp;
                nod = i;
            }
        }
        
    //printf ("%d\n", maxim); 
    Remake (nod, (1<<N) - 1);           
    
    printf ("%s\n", sol.c_str());
}

int
 main ()
{
    freopen ("adn.in", "rt", stdin);
    freopen ("adn.out", "wt", stdout);
    
    read ();
    solve ();
    
    return 0;
}