Cod sursa(job #825341)

Utilizator repp4raduRadu-Andrei Szasz repp4radu Data 28 noiembrie 2012 19:14:38
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.61 kb
#include <fstream>
#include <cstring>
#include <cstdio>

#define MAX 19
#define LMAX 30005
#define INF 0x3f3f3f3f

using namespace std;

int N;
int cost[MAX][MAX], P[LMAX], L[MAX], dp[(1 << MAX)][MAX], dad[(1 << MAX)][MAX];
char sir[MAX][LMAX];

void buildPrefix(int n)
{
    memset(P, 0, sizeof(P));
    int k = 0;
    for(int i = 2; i <= L[n]; i++)
    {
        while(k && sir[n][k + 1] != sir[n][i]) k = P[k];
        if(sir[n][k + 1] == sir[n][i]) k++;
        P[i] = k;
    }
}

int KMP(int n, int m)
{
    int k = 0;
    for(int i = 1; i <= L[m]; i++)
    {
        while(k && sir[n][k + 1] != sir[m][i]) k = P[k];
        if(sir[n][k + 1] == sir[m][i]) k++;
        if(k == L[n]) return -1;
    }
    return k;
}

void preprocess()
{
    for(int i = 0; i < N; i++)
        L[i] = strlen(sir[i] + 1);
    for(int i = 0; i < N; i++)
    {
        buildPrefix(i);
        for(int j = 0; j < N; j++)
            if(i != j && KMP(i, j) == -1)
            {
                memcpy(sir[i], sir[N - 1], LMAX);
                L[i] = L[N - 1];
                N--; i--;
                break;
            }
    }
    for(int i = 0; i < N; i++)
    {
        buildPrefix(i);
        for(int j = 0; j < N; j++)
            if(i != j) cost[j][i] = L[i] - KMP(i, j);
    }
}

void init()
{
    for(int i = 0; i < (1 << N); i++)
        for(int j = 0; j < N; j++)
            dp[i][j] = INF;
    for(int i = 0; i < N; i++)
        dp[(1 << i)][i] = L[i], dad[(1 << i)][i] = -1;
}

void afisare(int conf, int last)
{
    if(dad[conf][last] == -1) { printf("%s", sir[last] + 1); return; }
    afisare(conf ^ (1 << last), dad[conf][last]);
    printf("%s", sir[last] + (L[last] - cost[dad[conf][last]][last] + 1));
}


int main()
{
    ifstream in("adn.in");
    in>>N; in.get();
    for(int i = 0; i < N; i++) in.getline(sir[i] + 1, LMAX);
    in.close();
    preprocess();
    init();
    for(int conf = 1; conf < (1 << N); conf++)
    {
        for(int i = 0; i < N; i++)
        {
            if(!(conf & (1 << i))) continue;
            for(int j = 0; j < N; j++)
            {
                if(!(conf & (1 << j)) || i == j) continue;
                if(dp[conf][i] > dp[conf ^ (1 << i)][j] + cost[j][i])
                    dp[conf][i] = dp[conf ^ (1 << i)][j] + cost[j][i], dad[conf][i] = j;
            }
        }
    }
    int best = INF, indInf;
    for(int i = 0; i < N; i++)
        if(dp[(1 << N) - 1][i] < best) best = dp[(1 << N) - 1][i], indInf = i;
    freopen("adn.out", "w", stdout);
    afisare((1 << N) - 1, indInf);
    fclose(stdout);
    return 0;
}