Cod sursa(job #2685450)

Utilizator Iulia14iulia slanina Iulia14 Data 16 decembrie 2020 22:44:52
Problema ADN Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.36 kb
#include <fstream>
#include <cstring>
using namespace std;
ifstream cin ("adn.in");
ofstream cout ("adn.out");
int dp[(1 << 18)][20];
int prev[(1 << 18)][20];
char s[20][30005];
int l[20];
int pi[20][30005];
void dani(int ind)
{
    int now = 0, i;
    for (i = 2; i <= l[ind]; i++)
    {
        now = pi[ind][i - 1];
        while (now && s[ind][i] != s[ind][now + 1])
            now = pi[ind][now];
        if (s[ind][i] == s[ind][1 + now])
            now++;
        pi[ind][i] = now;
    }
}
int kmp(int x, int y)
{
    int now = 0, i;
    for (i = 1; i <= l[x]; i++)
    {
        while (now && s[x][i] != s[y][now + 1])
            now = pi[y][now];
        if (s[x][i] == s[y][1 + now])
            now++;
        if (now == l[y])
            return l[y];
    }
    return now;
}
int in[20];
int c[20][20];
void atrb(int i, int j)
{
    if (kmp(i, j) == l[j])
        in[j] = 1;
    else
        c[i][j] = -kmp(i, j);
}

void recon(int mask, int p)
{
    if (mask == (1 << p))
    {
        cout << s[p] + 1;
        return;
    }
    recon(mask ^ (1 << p), prev[mask][p]);
    cout << (s[p] + 1 - c[prev[mask][p]][p]);
}
int main()
{
    int n, final = 0, i, j, ans = 2e9, last;
    cin >> n;
    for (i = 0; i < n; i++)
        for (j = 0; j < (1 << n); j++)
            dp[j][i] = 2e9;
    for (i = 0; i < n; i++)
    {
        cin >> (s[i] + 1);
        l[i] = strlen(s[i] + 1);
        dani(i); ///bebe dani
    }
    for (i = 0; i < n; i++)
        for (j = i + 1; j < n; j++)
        {
            atrb(i, j);
            atrb(j, i);
        }
    for (i = 0; i < n; i++)
        if (!in[i])
        {
            final += (1 << i);
            dp[(1 << i)][i] = 0;
        }
    for (int mask = 1; mask < (1 << n); mask++)
        for (i = 0; i < n; i++)
            if (mask & (1 << i) && !in[i])
                for (j = 0; j < n; j++)
                    if (i != j && !in[j] && mask & (1 << j) && dp[mask][i] > dp[mask ^ (1 << i)][j] + c[j][i])
                    {
                        dp[mask][i] = min(dp[mask][i], dp[mask ^ (1 << i)][j] + c[j][i]);
                        prev[mask][i] = j;
                    }
    for (i = 0; i < n; i++)
        if (dp[final][i] < ans)
        {
            ans = dp[final][i];
            last = i;
        }
    recon(final, last);
    return 0;
}