Cod sursa(job #174338)

Utilizator perticas_catalinperticas catalin perticas_catalin Data 8 aprilie 2008 19:51:53
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.64 kb
#include<stdio.h>
#include<string.h>
FILE*fin=fopen("adn.in","r");
FILE*fout=fopen("adn.out","w");
#define maxn 30001
#define nrconfig 300000
int rez[2][nrconfig][11],p2[19],ad[19][19],sup[2*maxn],n;
char s[19][maxn],t[2*maxn];
void prefix(int x,int y)
{
  int i,dim1,dim2,k;
  dim1=strlen(s[y]);
  for(i=0;i<dim1;i++)
    t[i]=s[y][i];
  t[dim1]='#';
  dim2=strlen(s[x]);
  for(i=0;i<dim2;i++)
    t[dim1+i+1]=s[x][i];
  sup[1]=0;k=0;
  for(i=2;i<=dim1+dim2+1;i++)
  {
    while(k>0&&t[k]!=t[i-1]) k=sup[k];
    if(t[k]==t[i-1]) k++;
    sup[i]=k;
  }
  ad[x][y]=sup[dim1+dim2+1];
}
void rec(int config,int ultim)
{
  int last=rez[1][config][ultim],cfl=config-p2[ultim-1],i;

  if(last==0) fprintf(fout,"%s",s[ultim]);
  else
  {
    rec(cfl,last);
    int dim=strlen(s[ultim]);
    for(i=ad[last][ultim];i<dim;i++)
      fprintf(fout,"%c",s[ultim][i]);
  }
}
void pref(int ind)
{
  sup[1]=0;int k=0,dim=strlen(s[ind]),i;
  for(i=2;i<=dim;i++)
  {
    while(k>0&&s[ind][k]!=s[ind][i-1]) k=sup[k];
    if(s[ind][k]==s[ind][i-1]) k++;
    sup[i]=k;
  }
}
int kmp(int ind1,int ind2)
{
  int k=0,i,dim1=strlen(s[ind1]),dim2=strlen(s[ind2]);
  for(i=1;i<=dim1;i++)
  {
    while(k>0&&s[ind2][k]!=s[ind1][i-1]) k=sup[k];
    if(s[ind2][k]==s[ind1][i-1]) k++;
    if(k==dim2) return 1;
  }
  return 0;
}
int main()
{
  int i,j,k,lim,ultima_config,dim,ok;
  fscanf(fin,"%d",&n);
  for(i=1;i<=n;i++)
    fscanf(fin,"%s",&s[i]);
  fclose(fin);
  for(i=1;i<=n;i++)
  {
    dim=strlen(s[i]);
    ok=1;pref(i);
    for(j=1;j<i;j++)
      if(dim<=strlen(s[j])&&kmp(j,i))
      {
	ok=0;
	break;
      }
    if(ok)
      for(j=i+1;j<=n;j++)
	if(dim<=strlen(s[j])&&kmp(j,i))
	{
	  ok=0;
	  break;
	}
    if(!ok)
    {
      for(j=i;j<n;j++)
	strcpy(s[j],s[j+1]);
      n--;
      i--;
    }
  }
  for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
      prefix(i,j);
  p2[0]=1;
  for(i=1;i<=n;i++)
    p2[i]=p2[i-1]*2;
  lim=p2[n];
  for(i=0;i<lim;i++)
    for(j=1;j<=n;j++)
      rez[0][i][j]=-1;
  for(i=0;i<n;i++)
  {
    rez[0][p2[i]][i+1]=0;
    rez[1][p2[i]][i+1]=0;
  }
  for(i=1;i<lim;i++)
  {
    for(j=0;j<n;j++)
      if(i&p2[j])
      {
	if(i-p2[j]==0)
	  break;
	ultima_config=i-p2[j];
	for(k=0;k<n;k++)
	  if(ultima_config&p2[k])
	    if(rez[0][ultima_config][k+1]+ad[k+1][j+1]>rez[0][i][j+1])
	    {
	      rez[0][i][j+1]=rez[0][ultima_config][k+1]+ad[k+1][j+1];
	      rez[1][i][j+1]=k+1;
	    }
      }
  }
  int max=-1,pmax;
  for(j=1;j<=n;j++)
    if(rez[0][lim-1][j]>max)
    {
      max=rez[0][lim-1][j];
      pmax=j;
    }
  rec(lim-1,pmax);
  fclose(fout);
  return 0;
}