Pagini recente » Cod sursa (job #2582904) | Cod sursa (job #110262) | Cod sursa (job #504036) | Cod sursa (job #1151732) | Cod sursa (job #2787223)
#include <bits/stdc++.h>
#define pi pair<int, int>
#define mp make_pair
#define pb push_back
using namespace std;
const int inf = (int)1e7;
const int maxN = 18;
const int maxL = 30005;
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];
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;
}
if (k == n) {
uniq[x] = false;
}
}
return k;
}
vector<int> gen(pi curr) {
if (curr.first == -1) {
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);
uniq[i] = true;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j) {
cost[i][j] = lgp(j, i);
}
}
}
vector<int> validNodes;
for (int i = 0; i < n; i++) {
if (uniq[i]) {
validNodes.pb(i);
}
}
for (int mask = 0; mask < (1 << n); mask++) {
for (int i = 0; i < n; i++) {
dp[mask][i] = -inf;
}
}
for (int i = 0; i < n; i++) {
if (uniq[i]) {
dp[(1 << i)][i] = 0;
prv[(1 << i)][i] = mp(-1, 0);
}
}
vector<int> validMasks;
for (int mask = 0; mask < (1 << n); mask++) {
bool valid = true;
for (int i = 0; i < n; i++) {
if (!uniq[i] && (mask & (1 << i))) {
valid = false;
}
}
if (valid) {
validMasks.pb(mask);
}
}
for (int mask : validMasks) {
for (int u : validNodes) {
for (int v : validNodes) {
if (u != v && (mask & (1 << v)) && (mask & (1 << u))) {
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, cnt = n;
for (int i = 0; i < n; i++) {
if (!uniq[i]) {
all ^= (1 << i);
cnt--;
}
}
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;
}