Cod sursa(job #356422)

Utilizator marinMari n marin Data 14 octombrie 2009 19:11:24
Problema ADN Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.72 kb
#include <stdio.h>
#include <string.h>
#define DIM 30010
#define INF 2000000009

char *A[20];
int V[20];
int D[20];

int P[20][DIM];
int T[20][DIM];
int i, N, j, ii, jj, t, k, dn, max, maxim, x, c, d, pMaxim, b, a, last;

int C[20][20];

int X[20][1<<19];

int calc (int a, int b) {
	int max = -INF, i, pMax;
	if (X[a][b] != -INF) {
		return X[a][b];
	}
	for (i=1;i<=N;i++) 
		if ((i!=a) && (b & (1<<i))){
			c = b & ~(1<<i);
			c = C[a][i]+calc(i,c);
			if (c>max){
				max = c;
				pMax = i;
			}
		}
	T[a][b] = pMax;
	X[a][b] = max;

	return max;
}

int main(){
	FILE *f = fopen("adn.in","r");
	fscanf(f,"%d",&N);
	for (i=1;i<=N;i++) {
		A[i] = new char[DIM];
		fscanf(f,"%s",A[i]);
		
		for (j = (D[i] = strlen(A[i]))+1; j>0; j--)
			A[i][j] = A[i][j-1];
	}
	fclose(f);

	for (ii=1;ii<=N;ii++) {
		P[ii][1] = 0;
		for (i=2, k=0;i<=D[ii];i++) {
			while (A[ii][i] != A[ii][k+1] && k>0)
				k = P[ii][k];
			if (A[ii][i] == A[ii][k+1]) {
				k++;
				P[ii][i] = k;
			}
		}
	}
	
	for (ii=1;ii<N;ii++)
		for (jj=ii+1;jj<=N;jj++) {
			
			for (i=1,k=0;i<=D[jj];i++) {
				while (k && A[jj][i]!=A[ii][k+1])
					k = P[ii][k];
				if (A[jj][i] == A[ii][k+1]) {
					k++;
					if (k == D[ii]) {
						//A[ii] e subsir pentru B[ii], deci A[ii] trebuie eliminat
						V[ii] = 1;
					}
				}
			}

			for (i=1,k=0;i<=D[ii];i++) {
				while (k && A[ii][i]!=A[jj][k+1])
					k = P[jj][k];
				if (A[ii][i] == A[jj][k+1]) {
					k++;
					if (k == D[jj]) {
						V[jj] = 1;
					}
				}
			}
			
		}
				
	j = 0;
	for (i=1;i<=N;i++) {
		if (V[i] == 0) {
			j++;
			for (t=1;t<=D[i];t++)
				P[j][t] = P[i][t];
			D[j] = D[i];
			A[j] = A[i];
		}
	}
	N = j;
	
	
	for (ii=1;ii<=N;ii++)
		for (jj=1;jj<=N;jj++) 
			if (ii!=jj){
			
				for (i=1,k=0;i<=D[jj];i++) {
					while (k && A[jj][i]!=A[ii][k+1])
						k = P[ii][k];
					if (A[jj][i] == A[ii][k+1]) {
						k++;
						if (k == D[ii]) {
							//A[ii] e subsir pentru B[ii], deci A[ii] trebuie eliminat
							V[ii] = 1;
						}
					}
				}
				
				C[jj][ii] = k;
			}
	dn = ((1<<(N)) - 1)<<1;
			
	for (i=1;i<=N;i++) {
		for (j=0;j<=dn;j++)
			X[i][j] = -INF;
		X[i][0] = 0;
	}
			

	for (i=1;i<=N;i++) {
		x = calc(i,dn & ~(1<<i));
		if (x>maxim) {
			maxim = x;
			pMaxim = i;
		}
	}
	
	T[0][dn] = pMaxim;
	
	//printf("%d\n",maxim);
	//printf("%s\n",A[a]+1);
	//drum(pMaxim, dn & ~(1<<pMaxim));
	
	FILE *g = fopen("adn.out","w");
	a = pMaxim;
	b = dn & ~(1<<pMaxim);
	fprintf(g,"%s",A[a]+1);
	last = a;
	while (b) {
		c = T[a][b];
		//printf("%s\n",A[c]+1);
		fprintf(g,"%s",A[c]+C[last][c]+1);
		last = c;
		d = b & ~(1<<c);
		a = c;
		b = d;
	}
	fclose(g);
	
	return 0;
}