Pagini recente » Cod sursa (job #2699716) | Cod sursa (job #66251) | Cod sursa (job #2925982) | Cod sursa (job #1911584) | Cod sursa (job #2786017)
#include <bits/stdc++.h>
#define pi pair<int, int>
#define mp make_pair
#define pb push_back
using namespace std;
const int inf = (int)1e9;
const int maxN = 18;
const int maxL = (int)3e4;
int n;
char s[maxN][maxL + 2];
int lps[maxL + 2];
int cost[maxN][maxN];
int dp[(1 << maxN)][maxN];
bool uniq[maxN];
pi prv[(1 << maxN)][maxN];
bool included(int x, int y) {
int n = (int)strlen(s[x] + 1), m = (int)strlen(s[y] + 1);
lps[0] = lps[1] = 0;
for (int i = 2; i <= n; i++) {
int k = lps[i - 1];
while (k > 0 && s[x][k + 1] != s[x][i]) {
k = lps[k];
}
if (s[x][k + 1] == s[x][i]) {
lps[i] = k + 1;
} else {
lps[i] = 0;
}
}
int k = 0;
for (int i = 1; i <= m; i++) {
while (k > 0 && s[x][k + 1] != s[y][i]) {
k = lps[k];
}
if (s[x][k + 1] == s[y][i]) {
k++;
if (k == n) {
return true;
}
} else {
k = 0;
}
}
return false;
}
int lgp(int x, int y) {
int n = (int)strlen(s[x] + 1), m = (int)strlen(s[y] + 1);
lps[0] = lps[1] = 0;
string v = "!";
for (int i = 1; i <= n; i++) {
v.pb(s[x][i]);
}
v += "?";
for (int i = 1; i <= m; i++) {
v.pb(s[y][i]);
}
int k = 0;
for (int i = 2; i < (int)v.size(); i++) {
while (k > 0 && v[k + 1] != v[i]) {
k = lps[k];
}
if (v[k + 1] == v[i]) {
k++;
} else {
k = 0;
}
}
return k;
}
void dmp(int mask) {
for (int i = 0; i < n; i++) {
if (uniq[i]) {
cerr << (bool)(mask & (1 << i));
}
}
cerr << "\n";
}
string gen(pi curr) {
int mask = curr.first, u = curr.second;
dmp(mask);
if (!mask) {
return string("");
}
string result = gen(prv[mask][u]);
int v = prv[mask][u].second;
int n = (int)strlen(s[u] + 1);
for (int i = cost[v][u] + 1; i <= n; i++) {
result += s[u][i];
}
return result;
}
int main() {
assert(freopen("adn.in", "r", stdin));
assert(freopen("adn.out", "w", stdout));
cin >> n;
for (int i = 0; i < n; i++) {
cin >> (s[i] + 1);
}
for (int i = 0; i < n; i++) {
bool notIncluded = true;
for (int j = 0; j < n; j++) {
if (i != j && included(i, j)) {
notIncluded = false;
}
}
uniq[i] = notIncluded;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i != j) {
cost[i][j] = lgp(i, j);
}
}
}
for (int i = 0; i < n; i++) {
for (int mask = 0; mask < (1 << n); mask++) {
dp[mask][i] = -inf;
}
dp[(1 << i)][i] = 0;
}
for (int mask = 0; mask < (1 << n); mask++) {
for (int u = 0; u < n; u++) {
if ((mask & (1 << u)) && uniq[u]) {
for (int v = 0; v < n; v++) {
if ((mask & (1 << v)) && uniq[v] && u != v) {
int prevMask = mask ^ (1 << u);
if (dp[mask][u] < dp[prevMask][v] + cost[v][u]) {
dp[mask][u] = dp[prevMask][v] + cost[v][u];
prv[mask][u] = mp(prevMask, v);
}
}
}
}
}
}
int mx = -inf, start = -1;
int all = (1 << n) - 1;
for (int i = 0; i < n; i++) {
if (!uniq[i]) {
all ^= (1 << i);
}
}
for (int i = 0; i < n; i++) {
if (uniq[i] && mx < dp[all][i]) {
mx = dp[all][i];
start = i;
}
}
string result = gen(mp(all, start));
cout << result << "\n";
return 0;
}