Cod sursa(job #2433409)

Utilizator mihai50000Mihai-Cristian Popescu mihai50000 Data 27 iunie 2019 11:57:12
Problema ADN Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.57 kb
#include <bits/stdc++.h>

using namespace std;

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

const int INF = 1e8;

string s[20];
int prefix[20][30017];
int dp[(1 << 19)][20];
pair <int, int> from[(1 << 19)][20];
int c[20][20];

void build(int pos)
{
    int n = s[pos].size();

    s[pos] = ' ' + s[pos];

    int k = 0;

    for(int i = 2; i <= n; i++)
    {
        while(k != 0 && s[pos][k + 1] != s[pos][i])
            k = prefix[pos][k];

        if(s[pos][k + 1] == s[pos][i])
            k++;

        prefix[pos][i] = k;
    }
}

void get(int x, int y)
{
    if(c[y][x] == 0)
        return ;

    int m1 = s[x].size() - 1;
    int m2 = s[y].size() - 1;

    int k = 0;

    for(int i = 1; i <= m2; i++)
    {
        while(k != 0 && s[x][k + 1] != s[y][i])
            k = prefix[x][k];

        if(s[x][k + 1] == s[y][i])
            k++;

        if(k == m1)
        {
            c[y][x] = 0;
            return ;
        }

        if(i == m2)
        {
            c[y][x] = m1 - k;
            return ;
        }
    }
}

int last = -1;

void afiseaza(int mask, int p)
{
    if(from[mask][p] != make_pair(0, 0))
        afiseaza(from[mask][p].first, from[mask][p].second);

    if(last == -1)
    {
        out << s[p];
    }
    else
    {
        int m = s[p].size() - 1;
        for(int j = m - c[last][p] + 1; j <= m; j++)
            out << s[p][j];
    }

    last = p;
}

main()
{
    int n;
    in >> n;

    for(int i = 0; i < n; i++)
    {
        in >> s[i];
        build(i);
    }

    for(int j = 0; j < n; j++)
    {
        for(int i = 0; i < n; i++)
            c[i][j] = INF;

        for(int i = 0; i < (1 << n); i++)
            dp[i][j] = INF;
    }

    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
                if(i != j)
                    get(i, j);

    for(int i = 0; i < n; i++)
        dp[(1 << i)][i] = s[i].size() - 1;

    for(int i = 0; i < (1 << n); i++)
        for(int j = 0; j < n; j++)
            if(i & (1 << j))
                for(int k = 0; k < n; k++)
                    if(i & (1 << k))
                        if(dp[i][j] > dp[i ^ (1 << j)][k] + c[k][j])
                        {
                            dp[i][j] = dp[i ^ (1 << j)][k] + c[k][j];
                            from[i][j] = {i ^ (1 << j), k};
                        }

    int start = 0;

    for(int i = 0; i < n; i++)
        if(dp[(1 << n) - 1][i] < dp[(1 << n) - 1][start])
            start = i;

    afiseaza((1 << n) - 1, start);
}