Cod sursa(job #1488848)

Utilizator tudi98Cozma Tudor tudi98 Data 19 septembrie 2015 22:39:10
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.98 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <utility>
using namespace std;

const int Nmax = 18;
const int Lmax = 30000;
const int inf = 0x3f3f3f3f;

int pos[Nmax];
vector<string> A;
vector<int> Sol;
string a[Nmax];
bool out[Nmax];
int cost[Nmax][Nmax];
int pred[Nmax][1<<Nmax];
int C[Nmax][1<<Nmax];
int pi[Nmax][Lmax];
int N;

void PrefixFunction()
{
	for (int i = 0; i < N; i++)   // prefix function for string i
	{
		int k = -1;
		pi[i][0] = -1;
		for (int j = 1; j < a[i].size(); ++j)
		{
			while (k != -1 && a[i][k+1] != a[i][j])
				k = pi[i][k];
			if (a[i][k+1] == a[i][j]) ++k;
			pi[i][j] = k;
		}
	}
}

bool KMP(int s1,int s2)
{
	int k = -1;
	for (int i = 0; i < a[s1].size(); ++i)
	{
		while (k != -1 && a[s2][k+1] != a[s1][i])
			k = pi[s2][k];
		if (a[s1][i] == a[s2][k+1])
			++k;
		if (k == a[s2].size() - 1)
			return 1;
	}
	return 0;
}

void BuildCost()
{
	for (int s1 = 0; s1 < N; s1++)
		for (int s2 = 0; s2 < N; s2++)
		{
			if (s1 == s2) continue;
			int k = -1;
			for (int i = 0; i < A[s1].size(); ++i)
			{
				while (k != -1 && A[s2][k+1] != A[s1][i])
					k = pi[pos[s2]][k];
				if (A[s1][i] == A[s2][k+1])
				{	
					++k;
					if (i == A[s1].size() - 1)
						cost[s1][s2] = k+1;
				}
			}
		}
}
    
void HamiltonianPath()
{
	for (int i = 0; i < N; i++)
		for (int j = 0; j < 1<<N; j++)
			C[i][j] = -inf;

	for (int i = 0; i < N; i++)
		C[i][1<<i] = 0;

	for (int i = 0; i < 1 << N; i++)
		for (int j = 0; j < N; j++)
			if (i & (1 << j))
			{
				for (int k = 0; k < N; k++)
					if (i & (1 << k))
					{
						int curr = C[k][i ^ (1<<j)] + cost[k][j];
						if (curr >= C[j][i])
						{
							C[j][i] = curr;
							pred[j][i] = k;
						}
					}
			}
}

void TakeBestPath()
{
	int mask = (1<<N) - 1;
	int Max = 0;
	for (int i = 1; i < N; i++)
		if (C[Max][mask] < C[i][mask])
			Max = i;

   	for (int i = 0; i < N; i++)
	{
		Sol.push_back(Max);
		Max = pred[Max][mask];
		mask ^= (1<<Sol.back());
	}
}

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

	fin >> N;
	for (int i = 0; i < N; i++)
		fin >> a[i];

	PrefixFunction();

	for (int i = 0; i < N - 1; i++)
		for (int j = i+1; j < N; j++)
		{
			if (a[i].size() > a[j].size() && !out[j])
				out[j] = KMP(i,j);
			else if (a[i].size() <= a[j].size() && !out[i])
				out[i] = KMP(j,i);
		}

    for (int i = 0; i < N; i++)
   		if (!out[i])
   		{
   			pos[A.size()] = i;
   			A.push_back(a[i]);		
   		}

    N = A.size();
          
   	if (N == 1)
   	{
    	fout << A[0] << "\n";
    	return 0;
 	}

    BuildCost();                       
    HamiltonianPath();
	TakeBestPath();

	/*
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++)
			cout << cost[i][j] << " ";
		cout << "\n";
	}
	*/

	for (int i = N - 1; i >= 0; i--)
	{
		if (i == N - 1)
			fout << A[Sol[i]];
		else
			fout << A[Sol[i]].substr(cost[Sol[i+1]][Sol[i]]);
    }
}