Cod sursa(job #3353339)

Utilizator unomMirel Costel unom Data 6 mai 2026 11:08:55
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.77 kb
///NU INCERCA IN VIATA TA SA FACI KMP PE SIRURI INDEXATE DE LA 1
///DOAR FA ALGORITMUL DE KMP PE INDEXAT DE LA 0
///SI CAND COMPARI DACA SUNT EGALE PUNE +1
///SI ASTA A FOST TOT
///(EMOJI FERICIT DE LUAT IN BRATE)

#include <fstream>
#include <iostream>

using namespace std;

#define int long long

ifstream in("adn.in");
ofstream out("adn.out");
int n;
string s[20];
int useless[20];
int cost[20][20];
signed dp[20][262155];
signed last[20][262155];
string ans;
int lps[30005];
int INF = (1 << 30);

void build_lps(int ind)
{
    for(int i = 0; i<s[ind].size(); i++)
    {
        lps[i] = 0;
    }

    int i = 1;
    int j = 0;

    while(i < s[ind].size())
    {
        if(s[ind][i] == s[ind][j])
        {
            j++;
            lps[i] = j;
            i++;
        }
        else
        {
            if(j == 0)
            {
                i++;
            }
            else
            {
                j = lps[j - 1];
            }
        }
    }
}

int contains_secv(int x, int y)
{
    if(s[y].size() > s[x].size())
    {
        return 0;
    }

    build_lps(y);

    int i = 0;
    int j = 0;
    while(i < s[x].size())
    {
        if(s[x][i] == s[y][j])
        {
            i++;
            j++;

            if(j == s[y].size())
            {
                return 1;
            }
        }
        else
        {
            if(j == 0)
            {
                i++;
            }
            else
            {
                j = lps[j - 1];
            }
        }
    }

    return 0;
}

int same_pref_suf(int x, int y) //x e concatenat cu y
{
    build_lps(y);

    int i = 0;
    int j = 0;
    while(i < s[x].size())
    {
        if(s[x][i] == s[y][j])
        {
            i++;
            j++;

            if(j == s[y].size())
            {
                j = lps[j - 1];
            }
        }
        else
        {
            if(j == 0)
            {
                i++;
            }
            else
            {
                j = lps[j - 1];
            }
        }
    }

    return j;
}

signed main()
{
    in>>n;

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

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

            if(contains_secv(i, j) == 1)
            {
                useless[j] = 1;
            }
        }
    }

    for(int i = 0; i<n; i++)
    {
        if(useless[i] == 0)
        {
            continue;
        }

        swap(useless[i], useless[n - 1]);
        swap(s[i], s[n - 1]);

        n--;
        i--;
    }

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

            cost[i][j] = (int)s[j].size() - same_pref_suf(i, j);
//            cout<<i<<" "<<j<<" "<<same_pref_suf(i, j)<<'\n';
        }
    }

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

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

    for(int mask = 1; mask < (1 << n); mask++)
    {
        for(int i = 0; i<n; i++)
        {
            if(!(mask & (1 << i)))
            {
                continue;
            }

            for(int j = 0; j<n; j++)
            {
                if((mask & (1 << j)))
                {
                    continue;
                }

                if(dp[i][mask] + cost[i][j] < dp[j][mask | (1 << j)])
                {
                    dp[j][mask | (1 << j)] = dp[i][mask] + cost[i][j];
                    last[j][mask | (1 << j)] = i;
                }
            }
        }
    }

    int cur = 0;
    int mask = (1 << n) - 1;
    for(int i = 0; i<n; i++)
    {
        if(dp[i][(1 << n) - 1] < dp[cur][(1 << n) - 1])
        {
            cur = i;
        }
    }

    int lmin = dp[cur][(1 << n) - 1];
    int poz = lmin - 1;
    ans.resize(lmin);

    while(cur != -1)
    {
        int nxt = last[cur][mask];

        if(nxt == -1)
        {
            for(int i = 0; i<s[cur].size(); i++)
            {
                ans[i] = s[cur][i];
            }
            break;
        }

        int nr_char = cost[nxt][cur];
        int ind = (int)s[cur].size() - nr_char;

        for(int i = poz - nr_char + 1; i<=poz; i++)
        {
            ans[i] = s[cur][ind];
            ind++;
        }

        poz -= nr_char;
        mask ^= (1 << cur);
        cur = nxt;
    }

    out<<ans;

    return 0;
}