Pagini recente » Cod sursa (job #1246109) | Cod sursa (job #412877) | Cod sursa (job #71548) | Istoria paginii runda/simu/clasament | Cod sursa (job #2546764)
#include <fstream>
#include <iomanip>
#include <string>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <math.h>
#include <set>
#include <map>
#include <string.h>
#include <queue>
#include <stack>
#define INF 0x3f3f3f3f
using namespace std;
#ifdef DEBUG
string name = "data";
#else
string name = "adn";
#endif
ifstream fin(name + ".in");
ofstream fout(name + ".out");
#define MAXN 18
#define MAXL 30005
int ns;
int n;
string s[MAXN];
int pi[MAXN][MAXL];
int toRemove[MAXN];
int d[MAXN][MAXN];
vector<string> sf;
void buildPi(string &s, int *pi) {
int i = 1;
int j = 0;
while (i < s.size()) {
if (s[i] == s[j]) {
j++;
pi[i] = j;
i++;
} else {
if (j == 0) {
i++;
} else {
j = pi[j - 1];
}
}
}
}
bool contains(string &t, int i) {
string sb = s[i];
auto p = pi[i];
if (t.size() < sb.size()) {
return false;
}
i = 0;
int j = 0;
while (i < t.size()) {
if (t[i] == sb[j]) {
i++;
j++;
if (j >= sb.size()) {
return true;
}
} else {
if (j == 0) {
i++;
} else {
j = p[j - 1];
}
}
}
return false;
}
int computeOverlap(string &t, int i) {
string sb = sf[i];
auto p = pi[i];
i = 1;
int j = 0;
while (i < t.size()) {
if (t[i] == sb[j]) {
i++;
j++;
} else {
if (j == 0) {
i++;
} else {
j = p[j - 1];
}
}
}
return (int)(sb.size() - j);
}
void buildGraph() {
fin >> ns;
for (int i = 0; i < ns; ++i) {
fin >> s[i];
}
for (int i = 0; i < ns; ++i) {
buildPi(s[i], pi[i]);
}
for (int i = 0; i < ns; ++i) {
for (int j = 0; j < ns; ++j) {
if (!toRemove[i] && !toRemove[j] && i != j && contains(s[i], j)) {
toRemove[j] = true;
}
}
}
n = ns;
for (int i = 0; i < ns; ++i) {
if (!toRemove[i]) {
sf.push_back(s[i]);
} else {
n--;
}
}
memset(pi, 0, sizeof(pi));
for (int i = 0; i < ns; ++i) {
buildPi(s[i], pi[i]);
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i != j) {
d[i][j] = computeOverlap(sf[i], j);
} else {
d[i][j] = INF;
}
}
}
}
void gen(int k, int bit, int nrOne, vector<int> &result) {
if (bit > (n - nrOne)) {
return;
}
if (nrOne == 0) {
result.push_back(k);
return;
}
gen(k | (1 << bit), bit + 1, nrOne - 1, result);
gen(k, bit + 1, nrOne, result);
}
vector<int> genNr(int nrOne) {
vector<int> result;
if (nrOne == 0) {
result.push_back(0);
return result;
}
gen(0, 0, nrOne, result);
return result;
}
int best[(1 << MAXN) + 10][MAXN];
int parent[(1 << MAXN) + 10][MAXN];
void hamiltonianPath() {
memset(best, 0x3f, sizeof(best));
for (int i = 0; i < n; ++i) {
best[1 << i][i] = (int)sf[i].size();
}
for (int i = 2; i <= n; ++i) {
auto v = genNr(i);
for (int x: v) {
for (int bit = 0; bit < n; ++bit) {
for (int j = 0; j < n; ++j) {
if (!(x & (1 << j))) {
continue;
}
if (d[j][bit] != INF) {
if (best[x & (~(1 << bit))][j] + d[j][bit] < best[x][bit]) {
best[x][bit] = best[x & (~(1 << bit))][j] + d[j][bit];
parent[x][bit] = j;
}
}
}
}
}
}
int bestest = INF;
int lastNode = 0;
for (int i = 0; i < n; ++i) {
if (best[(1 << n) - 1][i] < bestest) {
bestest = best[(1 << n) - 1][i];
lastNode = i;
}
}
int state = (1 << n) - 1;
vector<int> sol;
while (state > 0) {
sol.push_back(lastNode);
int nextNode = parent[state][lastNode];
state = state & (~(1 << lastNode));
lastNode = nextNode;
}
reverse(sol.begin(), sol.end());
fout << sf[sol[0]];
for (int i = 1; i < sol.size(); ++i) {
int k = sol[i];
int l = sol[i - 1];
for (int j = (int)(sf[k].size() - d[l][k]); j < sf[k].size(); ++j) {
fout << sf[k][j];
}
}
}
int main() {
buildGraph();
hamiltonianPath();
return 0;
}