Pagini recente » Cod sursa (job #2273389) | Cod sursa (job #1698283) | Cod sursa (job #340026) | Cod sursa (job #2480435) | Cod sursa (job #2140089)
// long live automata theory and lambda calculus :}
#include <bits/stdc++.h>
using namespace std;
ifstream fi("adn.in");
ofstream fo("adn.out");
const int N = 18, M = 60005;
struct Edge {
int v, cost; };
vector<Edge> g[N];
int state[M], dp[N][1 << N], anc[N][1 << N];
int n;
vector<int> links;
vector<string> v;
static int kmp(string &a, string &b) {
string str = a + "#" + b;
int n = str.size();
memset(state, 0x00, 4 * n + 4);
state[0] = -1;
for (int p, i = 1; i < n; ++i) {
p = state[i - 1];
while (p >= 0 && str[p + 1] != str[i])
p = state[p];
if (str[p + 1] == str[i])
p+= 1;
state[i] = p; }
return state[n - 1] + 1; }
static bool in(string a, string b) {
int p, n = a.size(), m = b.size();
memset(state, 0x00, 4 * a.size() + 4);
state[0] = -1;
for (int i = 1; i < a.size(); ++i) {
p = state[i - 1];
while (p >= 0 && a[p + 1] != a[i])
p = state[p];
if (a[p + 1] == a[i])
p+= 1;
state[i] = p; }
p = -1;
for (int i = 0; i < b.size(); ++i) {
while (p >= 0 && (p + 1 >= a.size() || a[p + 1] != b[i]))
p = state[p];
if (a[p + 1] == b[i])
p+= 1;
if (p + 1 == a.size())
return true; }
return false; }
int main() {
string str;
int best, tmsk;
fi >> n;
v.resize(n);
for (auto &i: v)
fi >> i;
sort(begin(v), end(v), [&](const string &a, const string &b) {
return a.size() < b.size(); });
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j)
if (in(v[i], v[j])) {
v[i] = "";
break; }
partition(begin(v), end(v), [&](string &x) { return x != ""; });
while (v.back() == "")
v.pop_back();
n = v.size();
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) if (i != j)
g[i].push_back({j, v[j].size() - kmp(v[j], v[i])});
memset(dp, 0x3f, sizeof dp);
for (int i = 0; i < n; ++i)
dp[i][1 << i] = v[i].size();
for (int msk = 1; msk < (1 << n); ++msk)
for (int u = 0; u < n; ++u)
for (auto v: g[u]) if ((~msk & (1 << v.v)) && dp[u][msk] + v.cost < dp[v.v][msk | (1 << v.v)]) {
dp[v.v][msk | (1 << v.v)] = dp[u][msk] + v.cost;
anc[v.v][msk | (1 << v.v)] = u; }
best = 0, tmsk = (1 << n) - 1;
for (int i = 1; i < n; ++i)
if (dp[i][(1 << n) - 1] < dp[best][(1 << n) - 1])
best = i;
links.push_back(best);
for (int t, i = 1; i < n; ++i) {
t = best;
best = anc[best][tmsk];
tmsk^= 1 << t;
links.push_back(best); }
reverse(begin(links), end(links));
best = links[0];
str+= v[best];
for (int i = 1; i < n; ++i) {
for (auto l: g[best]) if (l.v == links[i]) {
str+= string(begin(v[l.v]) + v[l.v].size() - l.cost , end(v[l.v]));
break; }
best = links[i]; }
fo << str << endl;
cerr << str.size() << endl;
return 0; }