Pagini recente » Cod sursa (job #3293121) | Cod sursa (job #239883) | Cod sursa (job #143316) | Cod sursa (job #226590) | Cod sursa (job #3255325)
#include <bits/stdc++.h>
#define L 19
#define LL 30005
#define MASK_MAX (1 << L) + 5
#define BASE 27
#define MOD 1000000123
#define INVALID -1
#define INF 1000000001
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
int n, ans, best;
string str[L], auxstr[L], v[L];
int h[L][LL], cost[L][L], invMod[LL];
pair <int, char> ham[MASK_MAX][L];
vector <int> path;
bool kick[L];
int qexp(int a, int b) {
int p = 1;
while (b) {
if (b % 2 == 1)
p = 1LL * p * a % MOD;
a = 1LL * a * a % MOD;
b /= 2;
}
return p;
}
void buildInvMod() {
int p = 1;
invMod[0] = 1;
for (int i = 1; i < LL; i++) {
p = 1LL * p * BASE % MOD;
invMod[i] = qexp(p, MOD - 2);
}
}
int getHash(int word, int l, int r) {
return 1LL * (h[word][r] - h[word][l - 1] + MOD) * invMod[l - 1] % MOD;
}
void generateHam() {
n++;
for (int mask = 0; mask < (1 << n); mask++)
for (int node = 0; node < n; node++)
ham[mask][node] = {INVALID, INVALID};
ham[1][0] = {0, INVALID};
for (int mask = 1; mask < (1 << n); mask++)
for (int node = 1; node < n; node++) {
if ((mask & (1 << node)) || ham[mask | (1 << node)][node].first != INVALID)
continue;
ham[mask | (1 << node)][node] = {INF, INVALID};
for (int i = 0; i < n; i++)
if (ham[mask][i].first != INVALID && cost[i][node] != -1) {
if (ham[mask | (1 << node)][node].first > ham[mask][i].first + cost[i][node])
ham[mask | (1 << node)][node] = {ham[mask][i].first + cost[i][node], i};
}
if (ham[mask | (1 << node)][node].first == INF)
ham[mask | (1 << node)][node] = {INVALID, INVALID};
}
ans = INF;
best = -1;
for (int node = 1; node < n; node++) {
if (ham[(1 << n) - 1][node].first != INVALID) {
if (ans > ham[(1 << n) - 1][node].first) {
ans = ham[(1 << n) - 1][node].first;
best = node;
}
}
}
}
int main() {
fin >> n;
str[0] = "#X";
for (int i = 1; i <= n; i++) {
fin >> str[i];
str[i] = "#" + str[i];
for (int j = 1; j < (int)str[i].size(); j++)
h[i][j] = (1LL * h[i][j - 1] + 1LL * (str[i][j] - 'A' + 1) * qexp(BASE, j)) % MOD;
}
buildInvMod();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (str[i].size() >= str[j].size())
continue;
bool out = false;
for (int k = 1; k <= (int)str[j].size() - (int)str[i].size() + 1; k++)
if (getHash(i, 1, str[i].size() - 1) == getHash(j, k, k + str[i].size() - 2))
out = true;
if (out)
kick[i] = true;
}
}
int ind = 1;
for (int i = 1; i <= n; i++)
if (!kick[i])
auxstr[ind++] = str[i];
n = ind - 1;
for (int i = 1; i <= n; i++)
str[i] = auxstr[i];
for (int i = 1; i <= n; i++) {
for (int j = 1; j < (int)str[i].size(); j++)
h[i][j] = (1LL * h[i][j - 1] + 1LL * (str[i][j] - 'A' + 1) * qexp(BASE, j)) % MOD;
}
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
if (i == j) {
cost[i][j] = -1;
continue;
}
int c = str[j].size() - 1;
for (int k = 0; k < (int)str[j].size(); k++) {
if (str[i].size() - str[j].size() + k + 1 <= 0)
continue;
if (getHash(i, str[i].size() - str[j].size() + k + 1, str[i].size() - 1) == getHash(j, 1, str[j].size() - k - 1)) {
c = k;
break;
}
}
cost[i][j] = c;
}
}
generateHam();
int node = best, mask = (1 << n) - 1;
while (node != INVALID) {
path.push_back(node);
int aux = node;
node = ham[mask][node].second;
mask -= (1 << aux);
}
reverse(path.begin(), path.end());
for (int i = 1; i < (int)path.size(); i++)
for (int j = str[path[i]].size() - cost[path[i - 1]][path[i]]; j < (int)str[path[i]].size(); j++)
fout << str[path[i]][j];
fout << "\n";
return 0;
}