Cod sursa(job #1632493)

Utilizator lacraruraduRadu Matei Lacraru lacraruradu Data 6 martie 2016 10:19:43
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.28 kb
#include <cstring>
#include <fstream>
#include <iostream>

using namespace std;

ifstream in("adn.in");
ofstream out("adn.out");

#define N 19
#define L 30002

int n;
char A[N][L];
int pred[L];
int v[N];
bool ok[N];
int lst[N], vf[N * N], urm[N * N], cost[N * N], nvf = 0;
int d[1 << N][N];
int t[1 << N][N];
int costuri[N][N];
int rez[N], nrez = 0;

inline bool kmp1(int x, int y)
{
    int k = 0;
    int l1 = strlen(1 + A[x]);
    int l2 = strlen(1 + A[y]);

    for(int i = 1; i <= l1; i++)
        pred[i] = 0;

    for(int i = 2; i <= l1; i++)
    {
        while(k != 0 && A[x][i] != A[x][1 + k])
            k = pred[k];
        if(A[x][i] == A[x][1 + k])
            k++;
        pred[i] = k;
    }

    k = 0;
    for(int i = 1; i <= l2; i++)
    {
        while(k != 0 && A[y][i] != A[x][1 + k])
            k = pred[k];
        if(A[y][i] == A[x][1 + k])
            k++;
        if(k == l1)
            return 1;
    }
    return 0;
}

inline int kmp2(int x, int y)
{
    int k = 0;
    int l1 = strlen(1 + A[x]);
    int l2 = strlen(1 + A[y]);

    for(int i = 1; i <= l1; i++)
        pred[i] = 0;

    for(int i = 2; i <= l1; i++)
    {
        while(k != 0 && A[x][i] != A[x][1 + k])
            k = pred[k];
        if(A[x][i] == A[x][1 + k])
            k++;
        pred[i] = k;
    }

    for(int i = 1; i <= l2; i++)
    {
        while(k != 0 && A[y][i] != A[x][1 + k])
            k = pred[k];
        if(A[y][i] == A[x][1 + k])
            k++;
    }
    return k;
}

int main()
{
    in >> n;
    for(int i = 1; i <= n; i++)
    {
        in >> (1 + A[i]);
        v[i - 1] = i;
    }

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        {
          if(i != j && !ok[i] && !ok[j] && strlen(1 + A[i]) <= strlen(1 + A[j]) && kmp1(i, j))
                ok[i] = 1;
        }

    for(int i = 0; i < n; i++)
        while(ok[v[i]] && i < n)
        {
            swap(v[i], v[n - 1]);
            n--;
        }

    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(i != j)
            {
                vf[++nvf] = j;
                urm[nvf] = lst[i];
                cost[nvf] = kmp2(v[i], v[j]);
                lst[i] = nvf;
                costuri[j][i] = cost[nvf];
            }


    for(int i = 2; i < (1 << n); i++)
    {
        for(int j = 0; j < n; j++)
            if(i & (1 << j))
                for(int k = lst[j]; k; k = urm[k])
                    if(i & (1 << vf[k]) && d[i][j] <= (d[i - (1 << j)][vf[k]] + cost[k]))
                    {
                        d[i][j] = d[i - (1 << j)][vf[k]] + cost[k];
                        t[i][j] = vf[k];
                    }
    }

    int maxim = 0, imax = 0;
    for(int i = 0; i < n; i++)
    {
        if(d[(1 << n) - 1][i] > maxim)
        {
            maxim = d[(1 << n) - 1][i];
            imax = i;
        }
    }

    int mask = (1 << n) - 1;
    while(mask)
    {
        rez[++nrez] = imax;
        int aux = imax;
        imax = t[mask][imax];
        mask -= (1 << aux);
    }

    out << (1 + A[v[rez[nrez]]]);
    for(int i = nrez - 1; i > 0; i--)
        out << (1 + costuri[rez[i + 1]][rez[i]] + A[v[rez[i]]]);

    out << '\n';
    return 0;
}