Cod sursa(job #473958)

Utilizator blasterzMircea Dima blasterz Data 1 august 2010 21:53:07
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.61 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;


int n;

char a[20][30003];
int len[20];

int dist[20][20];
int t[30003];

int dp[(1 << 18) + 1][18];
int tata[ (1 << 18) + 1][18];

int calcDist (char a[], char p[], int n, int m)
{
	int i, k;
	memset (t, 0, sizeof (t));
	t[1] = 0;
	k = 0;

	for (i = 2; i <= m; ++i)
	{
		while (k && p[i] != p[k + 1])
			k = t[k];
		
		if (p[i] == p[k + 1])
			++k;
		t[i] = k;
	}
	
	k = 0;
	
	for (i = 1; i <= n; ++i)
	{
		while (k && a[i] != p[k + 1])
			k = t[k];
		
		if (a[i] == p[k + 1])
			++k;
		if (k == m)
			return m;

	}
	
	return k;
}

void brut ()
{
	int x[19];
	int sol[19];
	int mx = 0;
	int i;
	for (i = 1; i <= n; ++i)
		x[i] = i;
	
	
	int c = 0;
	
	do
	{
		c = 0;
		for (i = 2; i <= n; ++i)
			c += dist[x[i - 1]][x[i]];
		
		if (c >= mx)
		{
			mx = c;
			for (i = 1; i <= n; ++i)
				sol[i] = x[i];
		}
		
	}while (next_permutation (x + 1, x + n + 1));
	
	//for (i = 2; i <= n; ++i)
	//	printf ("%d\n", dist[sol[i - 1]][sol[i]]);

	printf ("(%d)\n", mx);
	
	for (i = 1; i <= n; ++i)
		printf ("%d ", sol[i]);
	printf ("__\n");
	printf ("%s", a[sol[1]] + 1);
	
	
	for (i = 2; i <= n; ++i)
	{
		if (dist[sol[i - 1]][sol[i]] != len[sol[i]])
			printf ("%s", a[sol[i]] + dist[sol[i - 1]][sol[i]]  + 1);
		
	}
	
	printf ("\n");
}

void doit ()
{
	int i, j, k;
	
	for (i = 0; i < (1 << n); ++i)
		for (j = 0; j < n; ++j)
			dp[i][j] = -0x3f3f3f3f, 
			tata[i][j] = -1;
		
	
	for (i = 0; i < n; ++i)
		dp[1 << i][i] = 0;
	
	
	for (i = 0; i < (1 << n); ++i)
		for (j = 0; j < n; ++j)
			if (i & (1 << j))
			{
				for (k = 0; k < n; ++k)
					if (j != k)	
					if (i & (1 << k))
						if (dp[i][j] < dp[i - (1 << j)][k] + dist[k + 1][j + 1])
							dp[i][j] = dp[i - (1 << j)][k] + dist[k + 1][j + 1],
							tata[i][j] = k ;
				
			}
	int mx = 0;
	int pi = -1;
	
	for (i = 0; i < n; ++i)
	{
		//printf ("%d\n", dp[(1 << n) -1][i]);
		if (dp[(1 << n) - 1][i] >= mx)
			mx = dp[(1 << n) - 1][i], 
			pi = i;
	}
	//printf ("%d\n", mx);

	i = (1 << n) - 1;
	
	vector <int> sol;
	
	for (j = pi; j != -1;  )
	{
		sol.push_back (j + 1);
		//printf ("%d ", j + 1);
		int r = j;
		j = tata[i][j];
		i -= 1 << r;
	}
	
	reverse (sol.begin (), sol.end ());


	printf ("%s", a[sol[0]] + 1);
	
	
	for (i = 1; i < n; ++i)
	{
		if (dist[sol[i - 1]][sol[i]] != len[sol[i]])
			printf ("%s", a[sol[i]] + dist[sol[i - 1]][sol[i]]  + 1);
		
	}
	
	printf ("\n");
}


int main ()
{
	freopen ("adn.in", "r", stdin);
	freopen ("adn.out", "w", stdout);
	
	scanf ("%d\n", &n);
	
	int i, j;
	
	for (i = 1; i <= n; ++i)
	{
		scanf ("%s\n", &a[i]);
		
		len[i] = strlen (a[i]);
		
		for (j = len[i]; j > 0; --j)
			a[i][j] = a[i][j - 1];
		a[i][len[i] + 1] = 0;
	
	//	printf ("%s\n", a[i] + 1);
	}
	
	for (i = 1; i <= n; ++i)
		for (j = 1; j <= n; ++j)
			if (i != j)
				dist[i][j] = calcDist (a[i], a[j], len[i], len[j]);
			
			
	int nr = 0;
	
	for (i = 1; i <= n; ++i)
	{
		int ok = 0;
		
		for (j = 1; j <= n; ++j)
			if (i != j)
				if (dist[j][i] == len[i])
				{
					ok = 1;
					break;
				}
				
		if (!ok)
		{
			++nr;
			for (j = 1; j <= len[i] + 1; ++j)
				a[nr][j] = a[i][j];
			len[nr] = len[i];
		}
		
		
	}
	
	n = nr;
	/*
	for (i = 1; i <= n; ++i)
	{
		fprintf (stderr, "%s\n", a[i] + 1);
		
	}
*/	
	for (i = 1; i <= n; ++i)
		for (j = 1; j <= n; ++j)
			if (i != j)
				dist[i][j] = calcDist (a[i], a[j], len[i], len[j]);

	

	//brut ();
	
	doit ();
	return 0;
}