Cod sursa(job #1732734)

Utilizator Cristian1997Vintur Cristian Cristian1997 Data 22 iulie 2016 14:39:08
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.34 kb
using namespace std;
#include <fstream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#define Nmax 18
#define Lmax 30010
#define INF 1000000000

int used, best[1 << Nmax][Nmax], pred[1 << Nmax][Nmax];
char words[Nmax][Lmax];
int G[Nmax][Nmax];

void make_phi(int[], char[]);
int kmp(char[], char[], int[]);

int main()
{
	int i, j, k, n, mask;
	int phi[Lmax], length[Nmax];
	ifstream fin("adn.in");
	ofstream fout("adn.out");

	(fin >> n).ignore();
	for (i = 0; i < n; ++i) { fin.getline(words[i] + 1, Lmax); length[i] = strlen(words[i] + 1); }

	for (i = 0; i < n; ++i)
	{
		make_phi(phi, words[i]);

		for (j = 0; j < n; ++j)
			if (i != j)
			{
				int ret = kmp(words[j], words[i], phi);

				if (ret == length[i]) { used |= 1 << i; break; }
				else G[j][i] = length[i] - ret;
			}
	}

	for (i = 1; i < (1 << n); ++i) for (j = 0; j < n; ++j) best[i][j] = INF;
	for (i = 0; i < n; ++i) best[1 << i][i] = length[i];

	for (i = 1; i < (1 << n); ++i)
		if ((i & used) == 0 && (i & (i - 1)))
		{
			for (j = 0; j < n; ++j)
				if (i & (1 << j))
				{
					for (k = 0; k < n; ++k)
						if (j != k && (i & (1 << k)) && best[i][j] > best[i ^ (1 << j)][k] + G[k][j])
							best[i][j] = best[i ^ (1 << j)][k] + G[k][j],
							pred[i][j] = k;
				}
		}

	mask = ((1 << n) - 1) ^ used;
	for (k = -1, j = 0; j < n; ++j)
	{
		if ((used & (1 << j)) == 0)
			if (k == -1 || best[mask][j] < best[mask][k])
				k = j;
	}

	string sol;
	for (i = mask; i; k = j)
	{
		j = pred[i][k];
		i ^= 1 << k;
		if(i) sol.insert(sol.begin(), words[k] + length[k] + 1 - G[j][k], words[k] + length[k] + 1);
		else sol.insert(sol.begin(), words[k] + 1, words[k] + length[k] + 1);
	}

	fout << sol << '\n';

	fin.close();
	fout.close();

    return 0;
}

void make_phi(int phi[], char s[])
{
	phi[1] = 0;
	for (int k = 0, i = 2; s[i]; ++i)
	{
		while (k && s[i] != s[k + 1]) k = phi[k];
		if (s[i] == s[k + 1]) ++k;
		phi[i] = k;
	}
}

int kmp(char s[], char p[], int phi[])
{
	int i, k;

	for (k = 0, i = 1; s[i]; ++i)
	{
		while (k && p[k + 1] != s[i])
			k = phi[k];
		if (p[k + 1] == s[i]) ++k;

		if (p[k + 1] == '\0') return k;
	}

	return k;
}