Pagini recente » Cod sursa (job #205391) | Cod sursa (job #1125937) | Cod sursa (job #1829153) | Cod sursa (job #2561857) | Cod sursa (job #2058611)
#include <fstream>
#include <vector>
using namespace std;
ifstream cin("adn.in");
ofstream cout("adn.out");
vector<int> GetPi(string s) {
int n = s.size();
vector<int> pi(n + 1, -1);
for (int i = 0; i < n; ++i) {
int j = pi[i];
while (j != -1 && s[i] != s[j])
j = pi[j];
pi[i + 1] = j + 1;
}
return pi;
}
vector<string> Prune(vector<string> strs) {
vector<string> ret;
for (auto s : strs) {
auto pi = GetPi(s);
bool match = false;
for (auto t : strs) {
if (t == s) continue;
int j = 0;
for (auto c : t) {
while (j != -1 && s[j] != c)
j = pi[j];
j += 1;
if (j == (int)s.size()) {
match = true;
break;
}
}
if (match) break;
}
if (!match) ret.push_back(s);
}
return ret;
}
int ComputeMid(string a, string b) {
auto pi = GetPi(b);
int j = 0;
for (auto c : a) {
while (j != -1 && b[j] != c)
j = pi[j];
j += 1;
}
return j;
}
int DP[1 << 18][18], Par[1 << 18][18];
int Mid[18][18];
vector<string> strs;
void Output(int c, int last) {
if (c == (1 << last)) cout << strs[last];
else {
Output(c ^ (1 << last), Par[c][last]);
int mid = Mid[Par[c][last]][last];
cout << strs[last].substr(mid);
}
}
int main() {
int n; cin >> n;
strs.resize(n);
for (int i = 0; i < n; ++i)
cin >> strs[i];
strs = Prune(move(strs));
n = strs.size();
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
Mid[i][j] = ComputeMid(strs[i], strs[j]);
for (int c = 0; c < (1 << n); ++c) {
for (int i = 0; i < n; ++i) {
if (!(c & (1 << i))) continue;
if (c == (1 << i)) DP[c][i] = strs[i].size();
else {
DP[c][i] = 1e9;
for (int j = 0; j < n; ++j) {
if (!(c & (1 << j)) or i == j) continue;
int now = DP[c ^ (1 << i)][j] + strs[i].size() - Mid[j][i];
if (DP[c][i] > now) {
DP[c][i] = now;
Par[c][i] = j;
}
}
}
}
}
int last = 0, c = ((1 << n) - 1);
for (int i = 0; i < n; ++i)
if (DP[c][i] < DP[c][last])
last = i;
Output(c, last); cout << endl;
return 0;
}