Cod sursa(job #2758749)

Utilizator popoviciAna16Popovici Ana popoviciAna16 Data 12 iunie 2021 13:44:28
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.77 kb
#include <fstream>
#include <string>
#include <vector>
using namespace std;

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

string s[18], a;
int p[60001];
int c[18][18];
int bij[18];

bool kmp (int x, int y)
{
	//calculez costul de la x la y
	int i, j;
	a = s[y] + '#' + s[x];
	
	for (i = 1; i<a.size(); i++)
	{
		j = p[i-1];
		while (j > 0 && a[i] != a[j])
			j = p[j-1];
		
		if (a[i] == a[j])
			j++;
		
		p[i] = j;
		if (p[i] == s[y].size())
			return 1;
	}
	
	c[x][y] = s[y].size() - p[a.size()-1];
	return 0;
}

int calc (int n)
{
	int m = 0, i, j;
	bool ok[18] = {};
	for (i = 0; i<n; i++)
		for (j = 0; j<n; j++)
			if (i != j)
				ok[j] = ok[j] | kmp(i, j);
	
	for (i = 0; i<n; i++)
		if (ok[i] == 0)
		{
			bij[m] = i;
			m++;
		}
	return m;
}

vector <int> v[19];
pair <int, int> dp[1<<18][18];
int rasp[20];

int main()
{
	int n, i, x, y, j, k;
	fin >> n;
	for (i = 0; i<n; i++)
		fin >> s[i];
	
	n = calc (n);
	
	for (i = 0; i < (1<<n); i++)
		v[__builtin_popcount(i)].push_back(i);
	
	for (i = 0; i<n; i++)
		dp[1<<i][i] = {s[bij[i]].size(), -1};
	
	for (i = 2; i<=n; i++)
		for (j = 0; j<v[i].size(); j++)
		{
			x = v[i][j];
			for (k = 0; k<n; k++)
				if (x & (1<<k))
				{
					dp[x][k] = {1<<30, 0};
					for (y = 0; y<n; y++)
						if ((x ^ (1<<k)) & (1<<y))
							dp[x][k] = min(dp[x][k], {dp[x ^ (1<<k)][y].first + c[bij[y]][bij[k]], y});
				}
		}
	
	x = 0;
	for (i = 1; i<n; i++)
		if (dp[(1<<n)-1][i].first < dp[(1<<n)-1][x].first)
			x = i;
	
	for (i = x, j = (1<<n)-1; i != -1; j = j ^ (1<<i), i = dp[j ^ (1<<i)][i].second)
		rasp[++rasp[0]] = i;
	
	fout << s[bij[rasp[rasp[0]]]];
	
	for (i = rasp[0] - 1; i>=1; i--)
	{
		x = c[bij[rasp[i+1]]][bij[rasp[i]]];
		for (j = s[bij[rasp[i]]].size() - x; j<s[bij[rasp[i]]].size(); j++)
			fout << s[bij[rasp[i]]][j];
	}
	return 0;
}