Cod sursa(job #2987802)

Utilizator Ilie_MityIlie Dumitru Ilie_Mity Data 2 martie 2023 21:26:49
Problema ADN Scor 70
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.44 kb
//Ilie Dumitru
#include<cstdio>
#include<cstring>
#include<algorithm>
const int NMAX=20;
const int LENMAX=30005;

int N, len[NMAX];
char mat[NMAX][LENMAX];
char* s[NMAX];
int prefix[NMAX][LENMAX];
int combine[NMAX][NMAX];
int parent[1<<NMAX][NMAX];
int dp[1<<NMAX][NMAX];

void genPrefix(int n)
{
	int i, q=0;

	for(i=1;i<=len[n];++i)
	{
		while(q && s[n][q]!=s[n][i])
			q=prefix[n][q];
		prefix[n][i]=q;
		if(q==0 || s[n][q]==s[n][i])
			++q;
	}
}

bool cmp(int i, int j)
{
	return len[i]<len[j];
}

int getExtra(int a, int b)
{
	int i, q=0;
	for(i=1;i<=len[b];++i)
	{
		while(q && s[a][q+1]!=s[b][i])
			q=prefix[a][q];
		if(s[a][q+1]==s[b][i])
			++q;
	}
	return len[a]-q;
}

void printSolution(int mask, int last, FILE* g)
{
	if(last!=-1)
	{
		printSolution(mask^(1<<last), parent[mask][last], g);
		int extra=parent[mask][last]==-1?len[last]:dp[mask][last]-dp[mask^(1<<last)][parent[mask][last]];
		fprintf(g, "%s", s[last]+len[last]-extra+1);
	}
}

int main()
{
	FILE* f=fopen("adn.in", "r"), *g=fopen("adn.out", "w");
	int i, j, mask, min;
	fscanf(f, "%d", &N);
	fgets(mat[0], LENMAX, f);
	mat[0][0]=0;
	for(i=0;i<N;++i)
	{
		fgets(mat[i]+1, LENMAX, f);
		s[i]=mat[i];
		len[i]=strlen(s[i]+1);
		if(s[i][len[i]]=='\n')
			s[i][len[i]--]=0;
		genPrefix(i);
	}

	for(i=0;i<N;++i)
	{
		for(j=0;j<N;++j)
		{
			if(i!=j && len[i]<=len[j])
			{
				if(strstr(s[j]+1, s[i]+1))
				{
					for(j=i+1;j<N;++j)
						s[j-1]=s[j], len[j-1]=len[j];
					--i;
					--N;
				}
			}
		}
	}

	for(i=0;i<N;++i)
		for(j=0;j<N;++j)
			if(i!=j)
				combine[i][j]=getExtra(j, i);

	for(i=0;i<N;++i)
	{
		for(j=0;j<N;++j)
			printf("%d ", combine[i][j]);
		printf("\n");
	}

	for(i=(1<<N)-1;i;--i)
	{
		for(j=0;j<N;++j)
		{
			dp[i][j]=NMAX*LENMAX;
			parent[i][j]=-1;
		}
	}

	for(i=0;i<N;++i)
		dp[1<<i][i]=len[i];

	for(mask=1;mask<(1<<N);++mask)
	{
		for(i=0;i<N;++i)
		{
			if(mask&(1<<i))
			{
				for(j=0;j<N;++j)
				{
					if((mask&(1<<j))==0)
					{
						//avem bit-ul i setat si bit-ul j nesetat
						if(dp[mask|(1<<j)][j]>dp[mask][i]+combine[i][j])
						{
							dp[mask|(1<<j)][j]=dp[mask][i]+combine[i][j];
							parent[mask|(1<<j)][j]=i;
						}
					}
				}
			}
		}
	}

	min=0;
	mask=(1<<N)-1;
	for(i=1;i<N;++i)
	{
		if(dp[mask][min]>dp[mask][i])
			min=i;
	}

	printSolution(mask, min, g);
	fflush(g);

	fclose(f);
	fclose(g);
	return 0;
}