Cod sursa(job #2027389)

Utilizator pas.andreiPopovici Andrei-Sorin pas.andrei Data 25 septembrie 2017 23:35:37
Problema ADN Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.89 kb
#include <bits/stdc++.h>
#define NMAX 30005
#define MOD 666013
#define INF 0x3f3f3f3f
#define x first
#define y second
#define pb push_back

using namespace std;

ifstream fin("adn.in");
ofstream fout("adn.out");

char s[20][NMAX],final[20*NMAX];
int pref[20][NMAX],dist[20][20],dp[1<<19][20],Prev[1<<19][20],lg[20];

void prefix(int care) {
	int i,p,n;

	p=0;
	n=lg[care];
	for(i=2;i<=n;++i) {
		while(p && s[care][p+1]!=s[care][i])
			p=pref[care][p];

		if(s[care][p+1] == s[care][i]) ++p;
		pref[care][i]=p;
	}
}

int calcDist(int a, int b) {
	int i,p,lg1=lg[a],lg2=lg[b];

	p=0;
	for(i=1;i<=lg1;++i) {
		while(p && s[b][p+1]!=s[a][i])
			p=pref[b][p];

		if(s[b][p+1] == s[a][i]) ++p;
		if(p==lg2) return -1;
	}

	return p;
}

int main() {
	int n,i,j,k=0,usable,x;

	fin>>n;
	usable=(1<<n)-1;
	for(i=1;i<=n;++i) {
		fin>>(s[i]+1);
		lg[i]=strlen(s[i]+1);
	}

	for(i=1;i<=n;++i) {
		for(j=1;j<=n;++j) {
			if(i==j) continue;

			x=calcDist(i,j);
			dist[i][j]=lg[j]-x;

			if(x==-1)
				usable=(usable&((1<<n)-1))-(1<<(j-1));
		}
	}

	for(i=0;i<=n;i++) {
		dist[i][0]=dp[0][i]=INF;
		dist[0][i]=lg[i];
	}

	dp[0][0]=0;
	for(i=1;i<=usable;i++) {
		dp[i][0]=INF;

		for(j=1;j<=n;j++) {
			dp[i][j]=INF;

			if(i&(1<<(j-1))) {
				for(k=0;k<=n;k++) {
					if(k==0 || ((i&(1<<(k-1))) && k!=j && dp[i][j]>dp[i^(1<<(j-1))][k]+dist[k][j])) {
						dp[i][j]=dp[i^(1<<(j-1))][k]+dist[k][j];
						Prev[i][j]=k;
					}
				}
			}
		}
	}
	int nod=1,pre=0,ind=0;
	for(int i=1;i<=n;i++)
		if(dp[usable][i]<dp[usable][nod])
			nod=i;

	stack<int> st;
	while(usable) {
		st.push(nod);
		usable^=(1<<(nod-1));
		nod=Prev[usable^(1<<(nod-1))][nod];
	}

	while(!st.empty()) {
		for(int i=lg[st.top()]-dist[pre][st.top()]+1;i<=lg[st.top()];i++)
			final[ind++]=s[st.top()][i];
		pre=st.top();
		st.pop();
	}

	fout<<final;

	return 0;
}