Cod sursa(job #79792)

Utilizator vladcoderVlad Ion vladcoder Data 23 august 2007 20:37:05
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.98 kb
#include <stdio.h>
#include <string.h>
#define MAX( a, b ) ( (a) > (b) ) ? a : b
#define MIN( a, b ) ( (a) < (b) ) ? a : b
#define FIN "adn.in"
#define FOUT "adn.out"
#define NMAX 19
#define LEN 30005

char A[NMAX][LEN];
char S[ 2 * LEN];
int PI[ 2 * LEN ], C[NMAX][NMAX];
int OUT[NMAX], P[NMAX];
int COST[NMAX][1<<NMAX];
int N, i, j, start;
FILE * fin, * fout;

void build_pi( char S[], int PI[] )
{
	int i, k = -1;
	PI[0] = -1;
	for( i = 1; i < strlen(S); i++ )
	{
		while ( ( k > -1 ) && ( S[i] != S[k+1] )) k = PI[k];
		if (S[i] == S[k+1]) k++;
		PI[i] = k;
	}
}
int KMP( char T[], char S[] ) 
{
	int k = -1, i;
    memset( PI, 0, sizeof( PI ));
	build_pi( S, PI );
	for( i = 0; i < strlen(T); i++)
	{
		while ( ( k > -1 ) && ( T[i] != S[k+1] ) ) k = PI[k];
		if ( T[i] == S[k+1] ) k++;
		if ( k == strlen(S) - 1 ) return 1;
	}
	return 0;
}
void elimin()
{
	int i, j;
	memset( OUT, 0, sizeof(OUT) );
	for( i = 1; i <= N; i++ )
		for( j = 1; j <= N; j++ )
			if ( (!OUT[j]) && ( i != j ) )
				if ( KMP( A[j], A[i] ) ) 
				{
					OUT[i] = 1;
					break;
				}
	int n = 0;
	for( i = 1; i <= N; i++ )
		if (!OUT[i])
		{
			n++; P[n] = i; // memorez indicii sirurilor ramase 
		}
		N = n;
}

void build_cost()
{
	int i, j;
	memset( C, 0, sizeof( C ) );
	for( i = 1; i <= N; i++ )
		for( j = 1; j <= N; j++)
			if ( i != j )
		{
			strcpy( S, A[P[j]] );
			strcat( S, "#" );
			strcat( S, A[P[i]] );
			build_pi( S, PI );
			C[i][j] = PI[ strlen(A[P[i]]) + strlen( A[P[j]] ) ] + 1;

		}
}

void dinamica()
{
	int i, j, k;
	for( j = 1; j <= (1 << N) - 1; j++)
		for( i = 0; i < N; i++)
			if ( (( 1 << i ) & j)  > 0 )
				for( k = 0; k < N; k++)
					if ( k != i )
					if ( (( 1 << k ) & j) > 0 )
						if ( COST[i+1][j] < COST[k+1][j - ( 1 << i )] + C[k+1][i+1] )
							COST[i+1][j] = COST[k+1][ j - ( 1 << i )] + C[k+1][i+1];
}


void reconst( int start )
{
	int p = 1, all = (1 << N ) - 1;
	int i;
	memset( OUT, 0, sizeof( OUT ) );
	OUT[p] = start; 
	while ( p < N )
	{
		for( i = 0; i < N; i++ )
		{
			if ( i+1 != start )
			if (( ( 1 << i ) & all ) > 0 )
				if ( COST[start][all] == COST[i+1][all - ( 1 << ( start-1))] + C[i+1][start])
				{
					all -= 1 << ( start - 1 );
					p++; OUT[p] = i+1;
					start = i+1;
					break;
				}
		}
	}
}

int main()
{
	fin = fopen( FIN, "r" );
	fout = fopen( FOUT, "w" );
	fscanf( fin, "%d\n", &N );
	for( i = 1; i <= N; i++ ) 
	{
		fgets( A[i], LEN, fin );
		A[i][ strlen(A[i]) - 1] = 0;
	}
   elimin();
   build_cost();
   dinamica();
   int max = 0;
   for( i = 1; i <= N; i++)
	   if ( COST[i][(1<<N)-1] > max ) 
	   {
		   max = COST[i][(1<<N)-1];
		   start = i;
	   }
   reconst( start );
   fputs( A[P[OUT[N]]], fout  );
   for( i = N - 1; i > 0; i--)
   {
      for( j = C[OUT[i+1]][OUT[i]]; j < strlen( A[P[OUT[i]]] ); j++ )
		  fprintf( fout, "%c", A[P[OUT[i]]][j] );
   }
   fprintf( fout, "\n");
   fclose( fin );
   fclose( fout );
	return 0;
}