Cod sursa(job #185355)

Utilizator andrei.12Andrei Parvu andrei.12 Data 25 aprilie 2008 09:51:55
Problema ADN Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.57 kb
#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;

#define infinit 0x3f3f3f3f
#define lg 18

int n, i, nr[lg], j, k, s, q, raspuns, d[lg][lg], a[lg][100000], urm[30005], gs, poz, pus[lg], nrs, sol[lg];
char fst[lg][100000], v[lg][30005];
const int pt[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};

void prefix(int ct){
	int k = 0;

	for (int i = 2; i <= nr[ct]; i ++){
		while (k > 0 && v[ct][k+1] != v[ct][i])
			k = urm[k];

		if (v[ct][k+1] == v[ct][i])
			k ++;

		urm[i] = k;
	}
}
int main()
{
	freopen("adn.in", "rt", stdin);
	freopen("adn.out", "wt", stdout);

	scanf("%d\n", &n);
	for (i = 1; i <= n; i ++){
		scanf("%s", v[i]+1);
		nr[i] = strlen(v[i]+1);
	}

	for (i = 1; i <= n; i ++)
		if (!pus[i]){
			memset(urm, 0, sizeof(urm));
			prefix(i);

			for (k = 1; k <= n; k ++)
				if (!pus[k] && i != k){
					s = 0, q = 0;
					
					for (j = 1; j <= nr[k]; j ++){
						while (q > 0 && v[i][q+1] != v[k][j])
							q = urm[q];

						if (v[i][q+1] == v[k][j])
							q ++;
						if (q == nr[i]){
							s = 1;
							break;
						}
						if (j == nr[k])
							gs = q;
					}

					if (s){
						pus[i] = 1;
						d[k][i] = nr[i];
					}
					else
						d[k][i] = gs;
					
				}
		}
	
	/*
	for (i = 1; i <= n; i ++)
		printf("%d ", nr[i]);
	printf("\n");
	for (i = 1; i <= n; i ++)
		for (j = 1; j <= n; j ++)
			printf("%d si %d --> %d\n", i, j, d[i][j]);
	*/
	for (i = 1; i <= n; i ++)
		if (pus[i])
			nrs |= pt[i];

	for (i = 1; i < (1 << n); i ++)
		for (j = 1; j <= n; j ++)
			a[j][i] = infinit;

	for (i = 1; i <= n; i ++)
		if (!pus[i])
			a[i][nrs | pt[i]] = nr[i];

	//printf("%d\n", nrs);
	for (j = 1; j < (1 << n); j ++)
		for (i = 1; i <= n; i ++)
			if (!pus[i])
				if (a[i][j] != infinit)
					for (k = 1; k <= n; k ++)
						if (!(j & pt[k]) && !pus[k]){
							int nxt = j | pt[k];
						
							if (a[i][j] + nr[k] - d[i][k] < a[k][nxt]){
								a[k][nxt] = a[i][j] + nr[k] - d[i][k];
								fst[k][nxt] = i;
							}
						}
	/*
	for (j = 1; j < (1 << n); j ++)
		for (i = 1; i <= n; i ++)
			printf("a[%d][%d] = %d -> %d\n", i, j, a[i][j], fst[i][j]);
	*/
	raspuns = infinit;
	for (i = 1; i <= n; i ++)
		if (a[i][(1 << n) - 1] < raspuns && !pus[i]){
			raspuns = a[i][(1 << n) - 1];
			poz = i;
		}
	
//	printf("%d %d\n", raspuns, poz);
	nrs = (1 << n) - 1;
	while (poz){
		sol[++sol[0]] = poz;

		int x = poz;
		poz = fst[poz][nrs];
		nrs ^= pt[x];
	}
	for (i = sol[0]; i; i --){
//		printf("%d\n", sol[i]);
		for (j = d[sol[i+1]][sol[i]]+1; j <= nr[sol[i]]; j ++)
			printf("%c", v[sol[i]][j]);
	}


	return 0;
}