Cod sursa(job #2918675)

Utilizator lolismekAlex Jerpelea lolismek Data 12 august 2022 15:16:55
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.68 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

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

const int N = 18, inf = 1e9 + 1;
int n, cost[N + 1][N + 1];
string vaux[N + 1], v[N + 1];
bool sus[N + 1];

int lsp(string a, string b){
	string s = "$" + b + "$" + a;
	vector <int> kmp((int)s.size(), 0);

	for(int i = 2; i < (int)s.size(); i++){
		int l = kmp[i - 1];
		while(l > 0 && s[l + 1] != s[i])
			l = kmp[l];
		if(s[l + 1] == s[i])
			kmp[i] = l + 1;
	}

	return (int)b.size() - kmp[(int)s.size() - 1];
}

bool sussy(string a, string b){
	string s = "$" + b + "$" + a;
	vector <int> kmp((int)s.size(), 0);

	for(int i = 2; i < (int)s.size(); i++){
		int l = kmp[i - 1];
		while(l > 0 && s[l + 1] != s[i])
			l = kmp[l];
		if(s[l + 1] == s[i])
			kmp[i] = l + 1;

		if(kmp[i] == (int)b.size())
			return true;
	}
	return false;
}

void calcCost(){
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			if(i != j){
				cost[i][j] = lsp(v[i], v[j]);
				cost[j][i] = lsp(v[j], v[i]);
			}
}

int dp[(1 << N)][N + 1], r[(1 << N)][N + 1];
vector <int> in[N + 1];

string HamiltonChain(){
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			if(i != j)
				in[i].push_back(j);
			
	for(int msk = 0; msk < (1 << n); msk++)
		for(int i = 0; i < n; i++)
			dp[msk][i] = inf;

	for(int i = 0; i < n; i++)
		dp[(1 << i)][i] = v[i].size();

	for(int msk = 1; msk < (1 << n); msk++)
		for(int i = 0; i < n; i++)
			if(msk & (1 << i))
				for(auto vec : in[i])
					if(msk & (1 << vec))
						if(dp[msk ^ (1 << i)][vec] + cost[vec][i] < dp[msk][i]){
							dp[msk][i] = dp[msk ^ (1 << i)][vec] + cost[vec][i];
							r[msk][i] = vec;
						}

	int cycLen = inf, last = 0;
	for(int i = 0; i < n; i++)
		if(dp[(1 << n) - 1][i] < cycLen)
			cycLen = dp[(1 << n) - 1][i], last = i;

	vector <int> sol;
	sol.push_back(last);

	int msk = (1 << n) - 1;

	for(int i = 1; i < n; i++){
		int aux = last;
		last = r[msk][last];
		msk -= (1 << aux);
		sol.push_back(last);
	}

	reverse(sol.begin(), sol.end());

	string ans = v[sol[0]];

	for(int i = 1; i < (int)sol.size(); i++){
		for(int j = (int)v[sol[i]].size() - cost[sol[i - 1]][sol[i]]; j < (int)v[sol[i]].size(); j++)
			ans += v[sol[i]][j];
	}
	
	return ans;
}

int main(){

	fin >> n;

	for(int i = 0; i < n; i++)
		fin >> vaux[i];

	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			if(i != j && sussy(vaux[i], vaux[j]))
				sus[j] = true;

	int m = 0;
	for(int i = 0; i < n; i++)
		if(!sus[i])
			v[m++] = vaux[i];

	n = m;

	calcCost();

	fout << HamiltonChain() << '\n';

	return 0;
}