Pagini recente » Cod sursa (job #41869) | Cod sursa (job #1289241) | Cod sursa (job #135869) | Cod sursa (job #2600787) | Cod sursa (job #1488848)
#include <fstream>
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
const int Nmax = 18;
const int Lmax = 30000;
const int inf = 0x3f3f3f3f;
int pos[Nmax];
vector<string> A;
vector<int> Sol;
string a[Nmax];
bool out[Nmax];
int cost[Nmax][Nmax];
int pred[Nmax][1<<Nmax];
int C[Nmax][1<<Nmax];
int pi[Nmax][Lmax];
int N;
void PrefixFunction()
{
for (int i = 0; i < N; i++) // prefix function for string i
{
int k = -1;
pi[i][0] = -1;
for (int j = 1; j < a[i].size(); ++j)
{
while (k != -1 && a[i][k+1] != a[i][j])
k = pi[i][k];
if (a[i][k+1] == a[i][j]) ++k;
pi[i][j] = k;
}
}
}
bool KMP(int s1,int s2)
{
int k = -1;
for (int i = 0; i < a[s1].size(); ++i)
{
while (k != -1 && a[s2][k+1] != a[s1][i])
k = pi[s2][k];
if (a[s1][i] == a[s2][k+1])
++k;
if (k == a[s2].size() - 1)
return 1;
}
return 0;
}
void BuildCost()
{
for (int s1 = 0; s1 < N; s1++)
for (int s2 = 0; s2 < N; s2++)
{
if (s1 == s2) continue;
int k = -1;
for (int i = 0; i < A[s1].size(); ++i)
{
while (k != -1 && A[s2][k+1] != A[s1][i])
k = pi[pos[s2]][k];
if (A[s1][i] == A[s2][k+1])
{
++k;
if (i == A[s1].size() - 1)
cost[s1][s2] = k+1;
}
}
}
}
void HamiltonianPath()
{
for (int i = 0; i < N; i++)
for (int j = 0; j < 1<<N; j++)
C[i][j] = -inf;
for (int i = 0; i < N; i++)
C[i][1<<i] = 0;
for (int i = 0; i < 1 << N; i++)
for (int j = 0; j < N; j++)
if (i & (1 << j))
{
for (int k = 0; k < N; k++)
if (i & (1 << k))
{
int curr = C[k][i ^ (1<<j)] + cost[k][j];
if (curr >= C[j][i])
{
C[j][i] = curr;
pred[j][i] = k;
}
}
}
}
void TakeBestPath()
{
int mask = (1<<N) - 1;
int Max = 0;
for (int i = 1; i < N; i++)
if (C[Max][mask] < C[i][mask])
Max = i;
for (int i = 0; i < N; i++)
{
Sol.push_back(Max);
Max = pred[Max][mask];
mask ^= (1<<Sol.back());
}
}
int main()
{
ifstream fin("adn.in");
ofstream fout("adn.out");
fin >> N;
for (int i = 0; i < N; i++)
fin >> a[i];
PrefixFunction();
for (int i = 0; i < N - 1; i++)
for (int j = i+1; j < N; j++)
{
if (a[i].size() > a[j].size() && !out[j])
out[j] = KMP(i,j);
else if (a[i].size() <= a[j].size() && !out[i])
out[i] = KMP(j,i);
}
for (int i = 0; i < N; i++)
if (!out[i])
{
pos[A.size()] = i;
A.push_back(a[i]);
}
N = A.size();
if (N == 1)
{
fout << A[0] << "\n";
return 0;
}
BuildCost();
HamiltonianPath();
TakeBestPath();
/*
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
cout << cost[i][j] << " ";
cout << "\n";
}
*/
for (int i = N - 1; i >= 0; i--)
{
if (i == N - 1)
fout << A[Sol[i]];
else
fout << A[Sol[i]].substr(cost[Sol[i+1]][Sol[i]]);
}
}