Cod sursa(job #3247073)

Utilizator Sasha_12454Eric Paturan Sasha_12454 Data 5 octombrie 2024 15:28:27
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.96 kb
#include <bits/stdc++.h>

const std :: string FILENAME = "adn";

std :: ifstream f (FILENAME + ".in");

std :: ofstream g (FILENAME + ".out");

const int NMAX = 18;

const int DIM = 3e4 + 5;

const int INF = 1e9;

short n;

short ind;

int cnt;

bool ok;

std :: vector <short> pi(2 * DIM);

std :: vector <std :: string> v(NMAX);

std :: bitset <NMAX> fr;

std :: string ans;

std :: vector <std :: vector <short>> dist(NMAX, std :: vector <short>(NMAX));

std :: vector <std :: vector <int>> dp((1 << NMAX), std :: vector <int>(NMAX));

std :: vector <std :: vector <short>> parent((1 << NMAX), std :: vector <short>(NMAX));

inline short pref(std :: string a, std :: string b)
{
    std :: string s = b + "#" + a;

    for(int i = 1; i < s.size(); i ++)
    {
        short j = pi[i - 1];

        while(j > 0 && s[i] != s[j])
        {
            j = pi[j - 1];
        }

        if(s[i] == s[j])
        {
            j ++;
        }

        pi[i] = j;
    }

    short k = pi[s.size() - 1];

    return k;
}

inline bool continut(std :: string a, std :: string b)
{
    std :: string s = a + "#" + b;

    for(int i = 1; i < s.size(); i ++)
    {
        short j = pi[i - 1];

        while(j > 0 && s[i] != s[j])
        {
            j = pi[j - 1];
        }

        if(s[i] == s[j])
        {
            j ++;
        }

        pi[i] = j;
    }

    for(int i = 0; i < s.size(); i ++)
    {
        if(pi[i] == a.size())
        {
            return true;
        }
    }

    return false;
}

int main()
{

    f >> n;

    for(short i = 0; i < n; i ++)
    {
        f >> v[i];
    }

    for(short i = 0; i < n; i ++)
    {
        ok = true;

        for(short j = 0; j < n; j ++)
        {
            if(i == j)
            {
                continue;
            }

            if(continut(v[i], v[j]))
            {
                ok = false;

                break;
            }
        }

        fr[i] = ok;
    }

    for(short i = 0; i < n; i ++)
    {
        if(fr[i])
        {
            v[cnt ++] = v[i];
        }
    }

    n = cnt;

    for(short i = 0; i < n; i ++)
    {
        for(short j = 0; j < n; j ++)
        {
            if(i == j)
            {
                continue;
            }

            dist[i][j] = pref(v[i], v[j]);
        }
    }

    for(short i = 0; i < n; i ++)
    {
        dp[(1 << i)][i] = v[i].size();
    }

    for(int i = 0; i < (1 << n); i ++)
    {
        for(int j = 0; j < n; j ++)
        {
            parent[i][j] = -1;
        }
    }

    for(int mask = 0; mask < (1 << n); mask ++)
    {
        for(short i = 0; i < n; i ++)
        {
            if(mask & (1 << i))
            {
                for(short j = 0; j < n; j ++)
                {
                    if((mask ^ (1 << i)) & (1 << j))
                    {
                        if((dp[mask][i] == 0) || (dp[mask ^ (1 << i)][j] + (int)v[i].size() - dist[j][i] < dp[mask][i]))
                        {
                            dp[mask][i] = dp[mask ^ (1 << i)][j] + (int)v[i].size() - dist[j][i];

                            parent[mask][i] = j;
                        }
                    }
                }
            }
        }
    }

    cnt = INF;

    for(short i = 0; i < n; i ++)
    {
        if(dp[(1 << n) - 1][i] < cnt)
        {
            cnt = dp[(1 << n) - 1][i];

            ind = i;
        }
    }

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

    while(parent[mask][ind] != -1)
    {
        int next = parent[mask][ind];

        std :: string aux = v[ind].substr(dist[next][ind]);

        std :: reverse(aux.begin(), aux.end());

        ans += aux;

        mask ^= (1 << ind);

        ind = next;
    }

    std :: reverse(v[ind].begin(), v[ind].end());

    ans += v[ind];

    std :: reverse(ans.begin(), ans.end());

    g << ans;

    return 0;
}