Cod sursa(job #2419303)

Utilizator Mihai145Oprea Mihai Adrian Mihai145 Data 7 mai 2019 23:12:05
Problema ADN Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.17 kb
#include <fstream>
#include <cstring>
#include <string>

using namespace std;

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

const int NMAX = 18;
const int CONFIGMAX = (1 << 18);
const int LMAX = 30001;
const int INF = 18 * 30001 + 100000;

int N;

int lg[NMAX + 5];
char str[NMAX + 5][LMAX + 5];

int cost[NMAX + 5][NMAX + 5];
bool useless[NMAX + 5];

int k;
int v[NMAX + 5];
int cost2[NMAX + 5][NMAX + 5];

int dp[CONFIGMAX + 5][NMAX + 5];
int pre[CONFIGMAX + 5][NMAX + 5];

string solll;

void Read()
{
    fin >> N;

    for(int i = 0; i < N; i++)
    {
        fin >> (str[i] + 1);
        lg[i] = strlen(str[i] + 1);
    }
}

int pi[LMAX + 5];

void InitPi(int ind)
{
    memset(pi, 0, sizeof(pi));

    int j = 0;

    for(int i = 2; i <= lg[ind]; i++)
    {
        while(j && str[ind][j + 1] != str[ind][i])
            j = pi[j];

        if(str[ind][j + 1] == str[ind][i])
            j++;

        pi[i] = j;
    }
}

void KMP(int p, int q)
{
    int j = 0;

    for(int i = 1; i <= lg[q]; i++)
    {
        while(j && str[p][j + 1] != str[q][i])
            j = pi[j];

        if(str[p][j + 1] == str[q][i])
            j++;

        if(j == lg[p])
        {
            useless[p] = 1;
            return ;
        }
    }

    cost[q][p] = lg[p] - j;
}

void GetCosts()
{
    for(int i = 0; i < N; i++)
    {
        InitPi(i);

        for(int j = 0; j < N; j++)
            if(i != j)
                KMP(i, j);
    }

    for(int i = 0; i < N; i++)
        if(useless[i] == 0)
            v[++k] = i;

    for(int i = 0; i < k; i++)
        for(int j = 0; j < k; j++)
            if(i != j)
                cost2[i][j] = cost[v[i]][v[j]];
}

int ksol;
int sol[NMAX + 5];

void Solve()
{
    for(int i = 0; i < (1 << k); i++)
        for(int j = 0; j < k; j++)
            dp[i][j] = INF;

    for(int i = 0; i < k; i++)
        dp[1 << i][i] = lg[v[i]];

    for(int config = 1; config < (1 << k); config++)
        for(int f = 0; f < N; f++)
            if(config & (1 << f))
                for(int j = 0; j < N; j++)
                    if(f != j && (config & (1 << j)))
                        if(dp[config ^ (1 << f)][j] + cost2[j][f] < dp[config][f])
                        {
                            dp[config][f] = dp[config ^ (1 << f)][j] + cost2[j][f];
                            pre[config][f] = j;
                        }

    int ans = INF, lastPos;

    for(int i = 0; i < k; i++)
        if(dp[(1 << k) - 1][i] < ans)
        {
            ans = dp[(1 << k) - 1][i];
            lastPos = i;
        }

    int mask = (1 << k) - 1;

    while(mask)
    {
        sol[++ksol] = lastPos;

        int prevPos = pre[mask][lastPos];

        mask = mask ^ (1 << lastPos);

        lastPos = prevPos;
    }

    int skip = 0;

    for(int i = ksol; i >= 1; i--)
    {
        for(int j = skip + 1; j <= lg[v[sol[i]]]; j++)
            solll += str[v[sol[i]]][j];

        skip = lg[v[sol[i - 1]]] - cost2[v[sol[i]]][v[sol[i - 1]]];
    }

    fout << solll;
}

int main()
{
    Read();

    GetCosts();

    Solve();

    return 0;
}