Pagini recente » Borderou de evaluare (job #1603669) | Cod sursa (job #2467852) | Cod sursa (job #831212) | Cod sursa (job #2356046) | Cod sursa (job #2787168)
#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)5e4;
int n;
char s[maxN][maxL + 2];
int lps[2 * 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);
memset(lps, 0, sizeof(lps));
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);
memset(lps, 0, sizeof(lps));
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;
}
vector<int> gen(pi curr) {
if (!curr.first) {
return vector<int>{};
}
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);
}
memset(uniq, true, sizeof(uniq));
for (int i = 0; i < n; i++) {
bool notIncluded = true;
for (int j = 0; j < n; j++) {
if (i != j && included(i, j) && uniq[j]) {
notIncluded = false;
}
}
uniq[i] = notIncluded;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j) {
cost[i][j] = lgp(j, i);
}
}
}
memset(dp, -inf, sizeof(dp));
for (int i = 0; i < n; i++) {
if (uniq[i]) {
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));
string str;
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]];
for (int j = c + 1; j <= sz; j++) {
str.pb(s[result[i]][j]);
}
}
}
cout << str << "\n";
return 0;
}