Cod sursa(job #132330)

Utilizator vlad_popaVlad Popa vlad_popa Data 5 februarie 2008 17:05:00
Problema ADN Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.34 kb
#include <cstdio>
#include <string>
#include <iostream>

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 (q == S[p1].length()-1)
            return -1;
    }
    
    return maxim = q;    
}

int Get_Cost (int i, int mask)
{
    mask -= (1 << i);
    //cout << i << "   " << mask << endl;
    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)
    {
        //cout << S[i] << " " << i << endl;
        if (S[i] != "")
            sol += S[i].substr(1, S[i].length()-1);
        return;
    }
        
    int p = pred[i][mask];
    //printf ("%s\n", S[i].c_str());
    //cout << p << " " << i << endl;
    Remake (p, mask);
    sol += S[i].substr(A[p][i]+1, S[i].length()-1);
    //cout << sol << endl;
}

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) == -1 && i != j)
                S[i] = "";
    
    for (i = 0; i < N; ++ i)
        for (j = 0; j < N; ++ j)
            if (S[j] != "" && S[i] != "" && i != j)
                A[j][i] = KMP (i, j, S[j].length()-1);
            else
                A[j][i] = 0;
    /*//cout << S[1] << endl << S[4]<< endl;
    //printf ("%d\n", KMP(4, 1, S[1].length()-1));
                
    for (i = 0; i < N; ++ i)
    {
        printf ("\n");
        for (j = 0; j < N; ++ j)
            printf ("%d ", A[i][j]);
    }*/
            
    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;
}