Cod sursa(job #2105779)

Utilizator FrequeAlex Iordachescu Freque Data 14 ianuarie 2018 10:59:17
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.31 kb
#include <bits/stdc++.h>

using namespace std;

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

const int NMAX = 18 + 5;
const int PMAX = (1 << 18) + 5;
const int LMAX = 30001 + 5;
const int INF = 0x3f3f3f3f;

vector <int> v;
int n;
int len[NMAX], phi[NMAX];
char lant[NMAX][LMAX];
bool useless[NMAX];
int comun[NMAX][NMAX];
int dp[NMAX][PMAX];

void prefix(int node)
{
    for (int i = 2; i <= len[node]; ++i)
    {
        int last = phi[i - 1];
        while (last > 0 && lant[node][i] != lant[node][last + 1]) last = phi[last];
        if (lant[node][i] == lant[node][last + 1]) phi[i] = last + 1;
    }
}

bool kmp (int pref, int node)
{
    int k = 0;
    for (int i = 1; i <= len[node]; ++i)
    {
        while (k > 0 && lant[node][i] != lant[pref][k + 1]) k = phi[k];
        if (lant[node][i] == lant[pref][k + 1]) ++k;

        if (k == len[pref])
        {
            comun[node][pref] = 0;
            return true;
        }

        if (i == len[pref] && comun[node][pref])
            comun[node][pref] = len[node] - k;
    }
    return false;
}

void read()
{
    fin >> n;
    for (int i = 1; i <= n; ++i)
    {
        fin >> (lant[i] + 1);
        len[i] = strlen(lant[i] + 1);
    }
}

int main()
{
    read();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            if (i != j)
            {
                comun[j][i] = -1;
                prefix(i);
                useless[i] = max(useless[i], kmp(i, j));
                //comun[j][i] = lant[j][len[j]];
            }

    for (int i = 1; i <= n; ++i)
        if (!useless[i])
            v.push_back(i);

    n = v.size();

    for (int conf = 1; conf < (1 << n); conf++)
        for (int i = 0; i < n; i++)
            if (conf & (1 << i))
            {
                dp[conf][i] = 1 << 30; /// inf

                int aux = conf - (1 << i);

                if (aux == 0) dp[conf][i] = len[v[i]];
                else for (int j = 0; j < n; j++)
                        if (aux & (1 << j))
                            dp[conf][i] = min(dp[conf][i], dp[aux][j] + len[v[i]] - comun[v[j]][v[i]]);
            }

    int sol = 1 << 30;
    for (int i = 0; i < n; i++)
        sol = min(sol, dp[(1 << n) - 1][i]);

    fout << sol << "\n";


    return 0;
}