Cod sursa(job #2432768)

Utilizator mihai50000Mihai-Cristian Popescu mihai50000 Data 24 iunie 2019 23:44:44
Problema ADN Scor 50
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.86 kb
#include <bits/stdc++.h>

using namespace std;

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

const int DIM = 18;
const int INF = 1e9;

int dp[(1 << DIM) + 7][DIM + 7];
pair <int, int> from[(1 << DIM) + 7][DIM + 7];
int c[DIM][DIM];
int prefix[DIM + 7][DIM + 7];

string s[DIM + 7];

vector <int> v[DIM + 7];

bool is[DIM + 7];


void build(int p)
{
    memset(prefix[p], 0, sizeof(prefix[p]));

    int k = 0;
    int n = s[p].size();

    s[p] = ' ' + s[p];

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

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

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

bool verifica(int x, int y)
{
    int k = 0;

    int n = s[x].size() - 1;
    int m = s[y].size() - 1;

    for(int i = 1; i <= m; 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 == n)
        {
            is[x] = true;
            return false;
        }

        if(i == m)
            c[y][x] = n - k;
    }

    return true;
}

vector <int> ind;

void print(int mask, int last, int p)
{
    if(p - 1)
        print(from[mask][last].first, from[mask][last].second, p - 1);

    int l = s[ind[last]].size() - 1;

    if(p == 1)
    {
        for(int i = 1; i <= l; i++)
            out << s[ind[last]][i];
    }
    else
    {
        for(int i = l - c[ind[from[mask][last].second]][ind[last]] + 1; i <= l; i++)
            out << s[ind[last]][i];
    }
}

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

    for(int i = 1; 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 = 1; i < n; i++)
        for(int j = i + 1; j <= n; j++)
        {
            verifica(i, j);
            verifica(j, i);
        }

    for(int i = 1; i <= n; i++)
        if(is[i] == false)
            ind.push_back(i);

    n = ind.size();

    for(int i = 0; i < n; i++)
        dp[(1 << i)][i] = s[ind[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 << j))
                        if(dp[i][j] > dp[i ^ (1 << j)][k] + c[ind[k]][ind[j]])
                        {
                            dp[i][j] = dp[i ^ (1 << j)][k] + c[ind[k]][ind[j]];
                            from[i][j] = {i ^ (1 << j), k};
                        }

    int start = 0;

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

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