Pagini recente » Cod sursa (job #871848) | Cod sursa (job #1807321) | Cod sursa (job #1549966) | Cod sursa (job #722875) | Cod sursa (job #2922742)
#include <bits/stdc++.h>
#define INF 1e9
#define LGMAX 300008
using namespace std;
ifstream fin ("adn.in");
ofstream fout ("adn.out");
int n;
int len[LGMAX], cost[20][20], dp[1<<20][20], pre[1<<20][20];
bool e_inclus[20];
string adn[20];
vector <int> sol;
void citire();
int KMP(string a, string b);
bool caut_subsir(string a, string b);
void create_graph();
void ciclu_hamiltonian();
int main()
{
citire();
create_graph();
ciclu_hamiltonian();
return 0;
}
void citire()
{
fin >> n;
for (int i = 0; i < n; i++)
fin >> adn[i];
}
int KMP(string a, string b)
{
string s = b + a;
for (int i = 1; i < s.size(); i++)
{
int j = len[i-1];
while (j > 0 && s[i] != s[j])
j = len[j-1];
if (s[i] == s[j])
j++;
len[i] = j;
}
return len[s.size()-1];
}
bool caut_subsir(string a, string b)
{
if (b.size() > a.size())
return 0;
string s = b + a;
for (int i = 1; i < s.size(); i++)
{
int j = len[i-1];
while (j > 0 && s[i] != s[j])
j = len[j-1];
if (s[i] == s[j])
j++;
len[i] = j;
if (len[i] == b.size())
return 1;
}
return 0;
}
void create_graph()
{
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (i != j)
{
if (e_inclus[j])
continue;
e_inclus[j] = caut_subsir(adn[i], adn[j]);
if (e_inclus[j])
{
if (adn[i].size() == adn[j].size())
{
e_inclus[min(i, j)] = 0;
e_inclus[max(i, j)] = 1;
}
continue;
}
int c = KMP(adn[i], adn[j]);
cost[i][j] = c;
}
}
void ciclu_hamiltonian()
{
int maxim = (1 << n);
for (int mask = 0; mask < maxim; mask++)
for (int j = 0; j < n; j++)
dp[mask][j] = INF;
for (int j = 0; j < n; j++)
dp[1<<j][j] = adn[j].size();
for (int mask = 0; mask < maxim; mask++)
for (int j = 0; j < n; j++)
{
if (e_inclus[j])
{
for (int i = 0; i < n; i++)
if (i != j)
{
if (dp[mask][j] > dp[mask ^ (1<<j)][i])
{
dp[mask][j] = dp[mask ^ (1<<j)][i];
pre[mask][j] = i;
}
}
continue;
}
if (!e_inclus[j] && (mask & (1 << j)))
for (int k = 0; k < n; k++)
if (k != j && (mask & (1 << k)))
{
int sz = adn[j].size();
if (dp[mask ^ (1<<j)][k] + sz - cost[k][j] < dp[mask][j])
{
dp[mask][j] = dp[mask ^ (1<<j)][k] + sz - cost[k][j];
pre[mask][j] = k;
}
}
}
int minim = INF;
maxim--;
int poz;
for (int i = 0; i < n; i++)
if (dp[maxim][i] < minim)
{
minim = dp[maxim][i];
poz = i;
}
if (!e_inclus[poz])
sol.push_back(poz);
for (int i = 1; i < n; i++)
{
int copie = poz;
poz = pre[maxim][copie];
maxim = maxim ^ (1 << copie);
if (!e_inclus[poz])
sol.push_back(poz);
}
//for (int i = sol.size()-1; i >= 0; i--)
//fout << sol[i] << ' ';
fout << adn[sol[sol.size()-1]];
for (int i = sol.size()-2; i >= 0; i--)
{
for (int j = cost[sol[i+1]][sol[i]]; j < adn[sol[i]].size(); j++)
fout << adn[sol[i]][j];
}
}