Cod sursa(job #1625925)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 2 martie 2016 21:24:02
Problema ADN Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.91 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];
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 = 0; 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-1;
    }
    return crt;
}

void process()
{
	for (int i = 0; i < n; i++)
		prefixes(i);
    for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
            if (i != j) {
				comun[i][j] = calculate(i, j)+1;
				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];
		}
	memo[nod][mask] = maxi;
	return maxi;
}

void getSolution(int ind)
{
    nods.push_back(ind);
    int crt = mask, p = ind;
    for (; crt != (1<<p); ) {
        for (int i = 0; i < n; i++)
			if (crt&(1<<i) && memo[i][crt-(1<<p)] + comun[i][p] == memo[p][crt]) {
                crt -= (1<<p);
                nods.push_back(i);
                p = i;
                break;
			}
    }
//    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);
        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;
}