Cod sursa(job #935728)

Utilizator radu124Radu Stefan radu124 Data 4 aprilie 2013 16:32:48
Problema ADN Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 3.68 kb
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

char seqs[18][30008];
int kmppre[30008];
int kmpl=0;
int n;
/**
 * dist[i][j] is the number of characters at the
 * end of i that are found in the beginning of j
 */
int dist[18][18];
int sol[18];
int32_t tsppre[262144][18];
int32_t tspm[262144][18];
int32_t tspord[4718592];

void solve();

int main(int argc, char *argv[])
{
	int i;
	FILE *fin=fopen("adn.in","r");
	fscanf(fin,"%d ",&n);
	for (i=0; i<n; i++)
	{
		fscanf(fin,"%s ",seqs[i]);
		//printf("%d %s\n",i,seqs[i]);
	}
	fclose(fin);
	solve();
	FILE *fou=fopen("adn.out","w");
	fprintf(fou,"%s",seqs[sol[0]]);
	//printf("%d",sol[0]);
	for (i=1; i<n; i++)
	{
		//printf(" %d",sol[i]);
		fprintf(fou,"%s",seqs[sol[i]]+dist[sol[i-1]][sol[i]]);
	}
	//fprintf(fou,"\n");
	fclose(fou);
}

/**
 * eliminate sequence i from the problem data and replace it by sequence
 * [n-1]
 */
void dropseq(int i)
{
	int j;
	//printf("Eliminated %d %s\n",i,seqs[i]);
	strcpy(seqs[i],seqs[n-1]);
	for (j=0; j<n; j++) dist[i][j]=dist[n-1][j];
	for (j=0; j<n; j++) dist[j][i]=dist[j][n-1];
	n--;
}

/**
 * for a corner case where one string is completely enclosed by another
 */
void dropseqs()
{
	int i,j,d;
	for (i=0; i<n; i++)
	{
		d=0;
		for (j=0; j<n; j++) d|=dist[j][i]<0;
		if (d) dropseq(i--);
	}
}

/*
G A G A G A T A G A G A T A
0 0 1 2 3 4 0 0 1 2 3 4 0 0

A A A B A A A A B
0 1 2 0 1 2 3 3 4
*/

/**
 * preprocessing for KMP, store result in kmppre
 */
void kmppreproc(const char *seq)
{
	int i,t;
	int l=strlen(seq);
	kmpl=l;
	kmppre[0]=0;
	//for (i=0; i<l; i++) printf("%c ",seq[i]);
	//printf("\n0 ");
	for (i=1; i<l; i++)
	{
		t=kmppre[i-1]+1;
		while (t>0)
		{
			if (seq[i]==seq[t-1]) break;
			t=(t==1)?0:(kmppre[t-2]+1);
		}
		kmppre[i]=t;
		//printf("%d ",t);
	}
	//printf("\n");
}

int kmpdist(const char *origseq, const int *kmppre, const char *seq)
{
	int l=strlen(seq);
	int i,r;
	r=0;
	for (i=0; i<l; i++)
	{
		r+=1;
		while (r>0)
		{
			if (seq[i]==origseq[r-1]) break;
			r=(r==1)?0:(kmppre[r-2]+1);
		}
		if (r==kmpl) return -1;
	}
	return r;
}

void printdist()
{
	int i,j;
	for (i=0; i<n; i++)
	{
		for (j=0; j<n; j++)
			printf("%2d ",dist[i][j]);
		printf("(%d) %s\n",i,seqs[i]);
	}
}

const char *nbin(int v)
{
	static char a[32];
	int i;
	for (i=0; i<n; i++)
		a[i]='0'+((v&(1<<i))!=0);
	a[n]=0;
	return a;
}

void tsp()
{
	int i,q,w;
	memset(tspm,0,sizeof(tspm));
	memset(tsppre,0,sizeof(tspm));
	q=0; // queue length
	w=0; // queue out
	for (i=0; i<n; i++)
	{
		tspm[1<<i][i]=1;
		tsppre[1<<i][i]=0;
		tspord[q++]=(1<<i)|(i<<18);
	}
	while (w<q)
	{
		int crtl=tspord[w++];
		int crtx=crtl;
		int crtb=crtl&0x3ffff;
		crtl>>=18;
		int crtm=tspm[crtb][crtl];
		//printf("Expanding %s/%d benefit:%d\n",nbin(crtb),crtl,crtm);
		for (i=0; i<n; i++)
		{
			if (crtb&(1<<i)) continue;
			int nxtb=crtb|(1<<i);
			int nxm=crtm+dist[crtl][i];
			//printf(" -> %s/%d benefit:%d",nbin(nxtb),i,nxm);
			if (tspm[nxtb][i]==0)
			{
				tspord[q++]=nxtb|(i<<18);
				//printf(" new");
			}
			if (nxm>tspm[nxtb][i])
			{
				tspm[nxtb][i]=nxm;
				tsppre[nxtb][i]=crtx;
				//printf(" better");
			}
			//printf("\n");

		}
	}
	int soll=0;
	int solx=(1<<n)-1;
	for (i=1; i<n; i++) if (tspm[solx][soll]<tspm[solx][i]) soll=i;
	q=n;
	while (solx!=0)
	{
		sol[--q]=soll;
		int soly=tsppre[solx][soll];
		//printf("Reconstruction benefit:%d pos:%d %s/%d\n",tspm[solx][soll],q,nbin(solx),soll);
		soll=soly>>18;
		solx=soly&0x3ffff;
	}
}

void solve()
{
	int i,j;
	for (i=0; i<n; i++)
	{
		sol[i]=i;
		kmppreproc(seqs[i]);
		for (j=0; j<n; j++) if (i!=j)
		{
			dist[j][i]=kmpdist(seqs[i],kmppre,seqs[j]);
			//printf("%s %d\n",seqs[j],dist[j][i]);
		}
		else dist[j][i]=0;
	}
//	printdist();
	dropseqs();
//	printdist();
	tsp();
}