Cod sursa(job #1626373)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 3 martie 2016 08:03:36
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.2 kb
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define MAXLEN 30050
#define MAXN 20

using namespace std;

char s[MAXN][MAXLEN];
int n, rez;
int comun[MAXN][MAXN], pref[MAXN][MAXLEN], memo[MAXN][1<<18];
int dad[MAXN][1<<18];
vector<int> nods;
vector<char> sol;
int mask;

void citire()
{
    scanf("%d\n", &n);
    for (int i = 0; i < n; i++) {
        gets(s[i]);
        int t = strlen(s[i]);
        for (int j = t; j >= 1; j--)
            s[i][j] = s[i][j-1];
    }
    mask = (1<<n)-1;
    for (int i = 0; i < n; i++)
        for (int j = 0; j <= mask; j++)
            memo[i][j] = -1;
}

void prefixes(int ind)
{
    pref[ind][1] = 0;
    int crt = 0;
    for (int i = 2, t = strlen(s[ind]); i < t; i++) {
        while (crt > 0 && s[ind][crt+1] != s[ind][i])
            crt = pref[ind][crt];
        if (s[ind][crt+1] == s[ind][i])
            crt++;
        pref[ind][i] = crt;
    }
}

int calculate(int x, int y)
{
    int crt = 0;
    for (int i = 1; s[x][i]; i++) {
        if (crt > 0 && s[y][crt+1] != s[x][i])
            crt = pref[y][crt];
        if (s[y][crt+1] == s[x][i])
            crt++;
        if (crt == strlen(s[y])-1)
            return crt;
    }
    return crt;
}

void process()
{
    for (int i = 0; i < n; i++)
        prefixes(i);
    for (int i = 0; i < n; i++) {
        if (mask & (1<<i))
            for (int j = 0; j < n; j++)
                if (i != j) {
                    comun[i][j] = calculate(i, j);
                    if (comun[i][j] == strlen(s[j])-1) {
                        mask &= ~(1<<j);
                    }
                }
    }
}

int hamilton(int nod, int mask)
{
    if (1<<nod == mask)
        memo[nod][mask] = 0;
    if (memo[nod][mask] != -1)
        return memo[nod][mask];
    int maxi = 0;
    for (int i = 0; i < n; i++)
        if (i!= nod && (mask&(1<<i))) {
            int val = hamilton(i, mask - (1<<nod));
            if (val + comun[i][nod] > maxi) {
                maxi = val + comun[i][nod];
                dad[nod][mask] = i;
            }
        }
    memo[nod][mask] = maxi;
    return maxi;
}

void getSolution(int ind)
{
    nods.push_back(ind);
    int aux;
    for (int conf = mask, p = ind; (1<<p)!=conf; aux = dad[p][conf], conf = conf-(1<<p), p = aux)
        nods.push_back(dad[p][conf]);
//    for (int i = nods.size()-1; i >= 0; i--)
//      printf("%d ", nods[i]);
//  printf("\n");
}

void solve()
{
//  for (int i = 0; i < n; i++, printf("\n"))
//      for (int j = 0; j < n; j++)
//          printf("%d ", comun[i][j]);
    rez = -1;
    int total = 0, pos = 0;
    for (int i = 0; i < n; i++) {
        if ((mask & (1<<i)) == 0)
            continue;
        int val = hamilton(i, mask);
        if (val > rez) {
            pos = i;
            rez = val;
        }
    }
    getSolution(pos);
    for (int i = 0; i < n; i++)
        total += strlen(s[i]);
    for (int i = nods.size()-1; i >= 0; i--) {
        int j =  (i < nods.size()-1 ? comun[nods[i+1]][nods[i]]+1 : 1);
        for (j; s[nods[i]][j]; j++)
            printf("%c", s[nods[i]][j]);
    }
    //printf("%d", total-rez);
}

int main()
{
    freopen("adn.in", "r", stdin);
    freopen("adn.out", "w", stdout);

    citire();
    process();
    solve();

    return 0;
}