Cod sursa(job #6595)

Utilizator t30Rosu Teodor t30 Data 20 ianuarie 2007 12:30:41
Problema ADN Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.22 kb
#include<stdio.h>
#include<string.h>
typedef struct nod { int x; nod *d; } nod;
nod *w[20];

int p[31000],OK,n,ok[20],v[20][20],qq[300000][20];
char s[20][31000];
long q[300000][20];

void init(int x)
{ int i,n,k,q;
  n=strlen(s[x])-1;
  for(i=0;i<=n;i++) p[i]=-1;
  n=strlen(s[x])-1;
  k=-1;
  for(q=1;q<=n;q++)
  {
	 while(k>=0 && s[x][k+1]!=s[x][i])
		k=p[k];
	 if(s[x][k+1]==s[x][q]) q++;
	 p[q]=k;
  }
}

int find(int x,int y)
{ OK=0;
  int n,m,q,i;
  m=strlen(s[x])-1;
  n=strlen(s[y])-1;
  q=-1;
  for(i=0;i<=n;i++)
  {
	  while(q>=0 && s[x][q+1]!=s[y][i])
		 q=p[q];
	  if(s[x][q+1]==s[y][i]) q++;
	  if(q==m) { q=p[q]; OK=1; }
  }
  return q+1;
}


void READ()
{  int i,j,x,y;
	FILE *f;
	f=fopen("adn.in","r");
	fscanf(f,"%d",&n);
	for(i=1;i<=n;i++)
	 fscanf(f,"%s",&s[i]);
	for(i=1;i<=n;i++)
	{  init(i);
		for(j=1;j<=n;j++)
		 if(ok[j]==0 && i!=j)
		  {
			 v[i][j]=find(i,j);
			 ok[i]=ok[i]||OK;
		  }
	}
	x=0; y=0;
	for(i=1;i<=n;i++)
	{
	  if(ok[i]==0)
	  { x++; y=0;
		 for(j=1;j<=n;j++)
			if(ok[j]==0) {
			  y++;
			  v[x][y]=v[i][j]; }
	  }
	}
	for(i=1;i<=n;i++)
	  if(ok[i]==1)
	  { for(j=i+1;j<=n;j++)
		 {	strcpy(s[j-1],s[j]);
			ok[j-1]=ok[j];
		 }


			n--;}

	fclose(f);
}


long maxim(long x,int k)
{ long max=-1,i;
  for(i=1;i<=n;i++)
	if(i!=k && x&(1<<(i-1)) && max< q[x - ((1<<(k-1)))][i]+v[i][k]) {
																				  max= (q[x -(1<<(k-1))][i]+v[i][k]);
																				  qq[x][k]=i; }
  return max;
}

void SOLVE()
{  long i,x,j;
	nod *p;
	for(i=1;i<(1<<n);i++)
	{
	  x=0;
	  j=i;
	  while(j)
	  {
		 x++;
		 j=j&(j-1);
	  }
	  p=new nod;
	  p->x=i;
	  p->d=w[x];
	  w[x]=p;
	}

	for(x=2;x<=n;x++)
	{
	  p=w[x];
	  while(p)
	  {
		 for(i=1;i<=n;i++)
		 if(p->x & (1<<(i-1)))	q[p->x][i]=maxim(p->x,i);
		 p=p->d;
	  }
	}
}




void PRINT()
{ int i,j,jj;
  long x;
  FILE *g;
  g=fopen("adn.out","w");
  j=1;
  for(i=1;i<=n;i++)
	 if(q[(1<<n)-1][i]>q[(1<<n)-1][j]) j=i;
  x=(1<<n)-1;

  while(x)
  { for(i=0;i<strlen(s[j])-(v[qq[x][j]][j]);i++)
		fprintf(g,"%c",s[j][i]);
	 jj=j;
	 j=qq[x][j];
	 x=x - (1<<(jj-1));

  }

  fclose(g);
}

int main()
{
READ();
SOLVE();
PRINT();
return 0;
}