Cod sursa(job #1749839)

Utilizator akaprosAna Kapros akapros Data 28 august 2016 21:18:00
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.87 kb
#include <bits/stdc++.h>
#define maxN 19
#define maxP (1 << 18)
#define maxL 30002
#define inf 1000000000
using namespace std;
int n, m, all, ans, cost[maxN][maxN], dp[maxN][maxP + 1], len[maxN];
int v[maxN], path[maxN];
char s[maxN][maxL], Ans[maxL * maxN];
void pref(int x)
{
    v[1] = 0;
    int i, k = 0;
    for (i = 2; i <= len[x]; ++ i)
    {
        while (k > 0 && s[x][i]!= s[x][k + 1])
            k = v[k];
        if (s[x][i] == s[x][k + 1])
            ++ k;
        v[i] = k;
    }
}
void read()
{
    int i;
    freopen("adn.in", "r", stdin);
    scanf("%d\n", &n);
    for (i = 0; i < n; ++ i)
    {
        gets(s[i] + 1);
        len[i] = strlen(s[i] + 1);
    }
}
int Cost(int x, int conf)
{
    int i, nod;
    if (dp[x][conf] != -1)
        return dp[x][conf];
    dp[x][conf] = inf;
    for (nod = 0; nod < n; ++ nod)
        if (nod != x && conf & (1 << nod))
        {
            if (nod == 0 && conf != (1 << x) + 1)
                continue;
            if (dp[x][conf] > Cost(nod, conf ^ (1 << x)) + cost[x][nod])
                dp[x][conf] = dp[nod][conf ^ (1 << x)] + cost[x][nod];
        }
    return dp[x][conf];
}
void init()
{
    all = (1 << n) - 1;
    memset(dp, -1, sizeof(dp));
    dp[0][1] = 0;
    dp[0][0] = 0;
    ans = inf;
}
void solve()
{
    int x, y;
    for (x = 0; x < n; ++ x)
        for (y = 0; y < n; ++ y)
            if (x != y)
            {
                cost[y][x] = -1;
                pref(y);
                int i, k = 0;
                for (i = 1; i <= len[x]; ++ i)
                {
                    while (k > 0 && s[x][i] != s[y][k + 1])
                        k = v[k];
                    if (s[x][i] == s[y][k + 1])
                        ++ k;
                    if (k == len[y])
                    {
                        cost[y][x] = 0;
                        break;
                    }
                }
                if (cost[y][x])
                    cost[y][x] = len[y] - k;
            }

    init();
    int i;
    for (i = 1; i < n; ++ i)
        if (Cost(i, all) < ans)
        {
            ans = dp[i][all];
            path[0] = i;
        }
    i = 0;
    while (all)
    {
        int j;
        for (j = 0; j < n; ++ j)
            if (dp[path[i]][all] == dp[j][all ^ (1 << path[i])] + cost[path[i]][j])
            {
                all ^= (1 << path[i]);
                path[++ i] = j;
                break;
            }
    }
}
void write()
{
    int i, j = n - 1, p = 1;
    freopen("adn.out", "w", stdout);
    //printf("%d\n", ans);
    for (j = 0; j < n; ++ j)
    {
        for (i = p; i <= len[path[j]]; ++ i)
            printf("%c", s[path[j]][i]);
        p = len[path[j + 1]] - cost[path[j]][path[j + 1]] + 1;
    }
}
int main()
{
    read();
    solve();
    write();
    return 0;
}