Cod sursa(job #134)

Utilizator ProstuStefan-Alexandru Filip Prostu Data 5 decembrie 2006 14:59:38
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.97 kb
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;
const int NMAX = 18;
const int MMAX = 30005;

int N, Nr;
char A[NMAX][MMAX];
int D[NMAX][NMAX];
bool V[NMAX];
int DP[NMAX][1 << NMAX], P[NMAX][1 << NMAX];

void citire() {
	FILE *fin = fopen("adn.in", "rt");
	int i;

	fscanf(fin, " %d", &N);
	Nr = N;
	for (i = 0; i < N; ++i)
		fscanf(fin, " %s", A[i]),
		V[i] = true;

	fclose(fin);
}

int kmp(char T[], char P[]) {
	int pi[MMAX];
	int i, j;
	int N, M;

	N = strlen(T);
	M = strlen(P);

	pi[0] = pi[1] = 0;
	for (j = 0, i = 2; i <= M; ++i) {
		while (j > 0 && P[j] != P[i - 1]) j = pi[j];
		if (P[j] == P[i - 1]) ++j;
		pi[i] = j;
	}

	for (j  = 0, i = 1; i <= N; ++i) {
		while (j > 0 && P[j] != T[i - 1]) j = pi[j];
		if (P[j] == T[i - 1]) ++j;
		if (j == M)
			return -1;
	}
	
	return M - j;
}

void graf() {
	int i, j, aux;

	memset(D, 0x3f, sizeof(D));
	for (i = 0; i < N; ++i)
		for (j = 0; j < N && V[i]; ++j)
			if (i != j && V[j]) {
				aux = kmp(A[i], A[j]);
				if (aux != -1)
					D[i][j] = aux;
				else
					V[j] = false,
					--Nr;
			}
}

int back(int k, int q, int c) {
	if (k == Nr) return 0;
	if (DP[c][q] != -1) return DP[c][q];

	int i, min, poz, aux;
	min = INF; poz = -1;
	for (i = 0; i < N; ++i)
		if ((q & (1 << i)) == 0 && V[i]) {
			aux = D[c][i] + back(k + 1, q | (1 << i), i);
			if (aux < min)
				min = aux,
				poz = i;
		}
	P[c][q] = poz;
	return DP[c][q] = min;
}

void afisare() {
	FILE *fout = fopen("adn.out", "wt");
	int i, min, poz, aux, t;

	min = INF; poz = -1;
	memset(DP, 0xff, sizeof(DP));
	for (i = 0; i < N; ++i)
		if (V[i]) {
			aux = strlen(A[i]) + back(1, 1 << i, i);
			if (min > aux)
				min = aux,
				poz = i;
		}
	
	
	fprintf(fout, "%s", A[poz]);
	aux = 1 << poz;
	for (i = 1; i < Nr; ++i) {
		t = P[poz][aux];
		fprintf(fout, "%s", A[t] + strlen(A[t]) - D[poz][t]);
		aux |= 1 << t;
		poz = t;
	}

	fprintf(fout, "\n");
	
	fclose(fout);
}

int main() {
	citire();
	graf();
	afisare();
	return 0;
}