Cod sursa(job #132379)

Utilizator vlad_popaVlad Popa vlad_popa Data 5 februarie 2008 18:45:01
Problema ADN Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.3 kb
#include <cstdio>
#include <string>
#include <iostream>

using namespace std;

#define NMAX 18

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

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

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

        if (S2[p][k + 1] == S2[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 && S2[p1][q + 1] != S2[p2][i])
            q = Pi[p1][q];

        if (S2[p1][q + 1] == S2[p2][i])
            ++ q;
        
        if (q == S2[p1].length()-1)
            return -1;
    }
    
    return maxim = q;    
}

int Get_Cost (int i, int mask)
{
    //cout << i << "   " << mask << endl;
    if (d[i][mask])
        return d[i][mask];
        
    int step;
    for (step = 1; step < mask; step <<= 1);
    if (step == mask)
        return 0;
        
    int j, tmp, maxim = -1, p = 0;    
    for (j = 1; j <= N; ++ j)
        if (mask & (1 << (j-1)) && j != i)
        {
            tmp = Get_Cost (j, mask - (1 << (i-1))) + 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)
{
    int p = pred[i][mask];
    
    if (!mask || !i)
        return;
    Remake (p, mask - (1<<(i-1)));
    
    if (d[i][mask] == d[p][mask-(1<<(i-1))] + A[p][i] && p != 0)
        printf ("%s", S2[p].substr(1, S2[p].length()-1-A[p][i]).c_str());
}

void solve ()
{
    int i, j;
    
    for (i = 1; i <= N; ++ i)
    {
        int l = S2[i].length()-1;
        Prefix (i, l);
    }
        
    for (i = 1; i <= N; ++ i)
        for (j = 1; j <= N; ++ j)
            if (KMP (i, j, S2[j].length()-1) == -1 && i != j)
                S2[i] = "";
    
    int ct1 = 0, ct2;
    for (i = 1; i <= N; ++ i)
    {
        if (S2[i] == "")
            continue;
        ++ ct1;
        ct2 = 0;
        for (j = 1; j <= N; ++ j)
            if (S2[j] != "")
                A[++ct2][ct1] = KMP (i, j, S2[j].length()-1);
    }
    
    ct1 = 0;
    for (i = 1; i <= N; ++ i)
        if (S2[i] != "")
            S2[++ct1] = S2[i];
    N = ct1;        
    
    /*for (i = 1; i <= N; ++ i)
    {
        printf ("\n");
        for (j = 1; j <= N; ++ j)
            printf ("%d ", A[i][j]);
    }*/
    int maxim = -1, nod, tmp;
    for (i = 1; i <= N; ++ 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", S2[nod].substr(1).c_str());
}

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