Pagini recente » Cod sursa (job #2937334) | Cod sursa (job #46596) | Cod sursa (job #2949793) | Cod sursa (job #1439796) | Cod sursa (job #2786026)
#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";
}
vector<int> gen(pi curr) {
// dmp(mask);
if (!curr.first) {
return vector<int>{};
}
// int v = prv[mask][u].second;
// int n = (int)strlen(s[u] + 1);
//// cerr << s[curr.second] + 1 << "\n";
// string result = gen(prv[mask][u]), result1;
//// cerr << result << " " << cost[v][u] << "\n";
// for (int i = cost[v][u] + 1; i <= n; i++) {
// result1 += s[u][i];
// }
vector<int> result = gen(prv[curr.first][curr.second]);
result.pb(curr.second);
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(j, i);
}
}
}
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;
}
}
vector<int> result = gen(mp(all, start));
// reverse(result.begin(), result.end());
string str;
// for (int x : result) {
// cerr << s[x] + 1 << "\n";
// }
// return 0;
for (int i = 0; i < (int)result.size(); i++) {
if (i == 0) {
int sz = (int)strlen(s[result[i]] + 1);
for (int j = 1; j <= sz; j++) {
str.pb(s[result[i]][j]);
}
} else {
int sz = (int)strlen(s[result[i]] + 1);
int c = cost[result[i - 1]][result[i]];
// cerr << c << "\n";
for (int j = c + 1; j <= sz; j++) {
str.pb(s[result[i]][j]);
}
}
}
cout << str << "\n";
// for (int x : result) {
// cerr << s[x] + 1 << "\n";
// }
return 0;
}