Pagini recente » Cod sursa (job #415917) | Cod sursa (job #2882628) | Cod sursa (job #3205643) | Cod sursa (job #2104524) | Cod sursa (job #2151373)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
const int NMAX = 18 + 5;
const int PMAX = (1 << 18) + 5;
const int LMAX = 30001 + 5;
const int INF = 0x3f3f3f3f;
vector <int> v;
int n;
int len[NMAX], phi[NMAX];
char lant[NMAX][LMAX];
bool useless[NMAX];
int comun[NMAX][NMAX];
int dp[NMAX][PMAX];
int prv[NMAX][PMAX]; /// indicele sirului pus inaintea ultimului
void prefix(int node)
{
for (int i = 2; i <= len[node]; ++i)
{
int last = phi[i - 1];
while (last > 0 && lant[node][i] != lant[node][last + 1]) last = phi[last];
if (lant[node][i] == lant[node][last + 1]) phi[i] = last + 1;
}
}
bool kmp (int pref, int node)
{
int k = 0;
for (int i = 1; i <= len[pref]; ++i)
{
while (k > 0 && lant[pref][i] != lant[node][k + 1]) k = phi[k];
if (lant[pref][i] == lant[node][k + 1]) ++k;
if (k == len[node])
{
comun[pref][node] = len[node];
return true;
}
}
comun[pref][node] = k;
return false;
}
void read()
{
fin >> n;
for (int i = 1; i <= n; ++i)
{
fin >> (lant[i] + 1);
len[i] = strlen(lant[i] + 1);
}
}
void Copiaza(char* A, string& ans, int x, int y, int w, int z)
{
int lung = z - w + 1;
for (int i = 0; i < lung; i++)
ans[w + i] = A[x + i];
}
string Reconst(int index)
{
int conf = (1 << n) - 1;
string ans;
ans.resize(dp[conf][index]);
int lung = dp[conf][index] - 1;
while (conf > 0)
{
/// pun pe index
int comun_prv = 0;
int nxt = v[prv[conf][index]];
int aux = conf - (1 << index);
if (aux != 0)
comun_prv = comun[nxt][v[index]];
Copiaza(lant[v[index]], ans, comun_prv + 1, len[v[index]], lung - (len[v[index]] - comun_prv) + 1, lung);
lung -= (len[v[index]] - comun_prv);
index = prv[conf][index];
conf = aux;
}
return ans;
}
int main()
{
read();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (i != j)
{
prefix(j);
useless[j] = max(useless[j], kmp(i, j));
//comun[j][i] = lant[j][len[j]];
}
for (int i = 1; i <= n; ++i)
if (!useless[i])
v.push_back(i);
n = v.size();
for (int conf = 1; conf < (1 << n); conf++)
for (int i = 0; i < n; i++)
if (conf & (1 << i))
{
dp[conf][i] = 1 << 30; /// inf
int aux = conf - (1 << i);
if (aux == 0) dp[conf][i] = len[v[i]];
else for (int j = 0; j < n; j++)
if (aux & (1 << j))
if (dp[conf][i] > dp[aux][j] + len[v[i]] - comun[v[j]][v[i]])
{
dp[conf][i] = dp[aux][j] + len[v[i]] - comun[v[j]][v[i]];
prv[conf][i] = j;
}
}
int sol = 1 << 30, ind;
for (int i = 0; i < n; i++)
if (sol > dp[(1 << n) - 1][i])
{
sol = dp[(1 << n) - 1][i];
ind = i;
}
/// reconstructia lui dp[(1 << n) - 1][ind]
string str_sol = Reconst(ind);
fout << str_sol << "\n";
return 0;
}