Pagini recente » Cod sursa (job #420752) | Cod sursa (job #2660677) | Cod sursa (job #753276) | Cod sursa (job #2791599) | Cod sursa (job #2177378)
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pdd pair<ld, ld>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
ifstream fin("adn.in");
ofstream fout("adn.out");
const int kInf = 1LL << 29;
int n;
vector<string> s;
vector<bool> ignored;
vector<vector<int>> cost;
vector<vector<int>> dp;
vector<vector<pii>> where;
class KMP {
public:
explicit KMP(const string& text) : text_(text) {}
pair<int, int> GetMatchingIndexes(const string& pattern) {
int count = 0;
vector<int> prefix(pattern.size(), 0);
BuildPi(pattern, prefix);
int q = 0;
for (int i = 0; i < (int)text_.size(); i++) {
while (q && pattern[q] != text_[i]) {
q = prefix[q - 1];
}
if (pattern[q] == text_[i]) {
q++;
}
if (q == (int)pattern.size()) {
count++;
}
}
return {count, q};
}
private:
void BuildPi(const string& pattern, vector<int>& prefix) {
int q = 0;
for (int i = 1; i < (int)pattern.size(); i++) {
while (q && pattern[q] != pattern[i]) {
q = prefix[q - 1];
}
if (pattern[q] == pattern[i]) {
q++;
}
prefix[i] = q;
}
}
const string text_;
};
void Read() {
fin >> n;
s.resize(n);
for (int i = 0; i < n; i++) {
fin >> s[i];
}
}
void BuildGraph() {
ignored.resize(n);
cost.resize(n, vector<int>(n, kInf));
for (int i = 0; i < n; i++) {
if (!ignored[i]) {
KMP kmp(s[i]);
for (int j = 0; j < n; j++) {
if (j != i && !ignored[j]) {
pii match = kmp.GetMatchingIndexes(s[j]);
if (match.fi) {
ignored[j] = 1;
} else {
cost[i][j] = s[j].size() - match.se;
}
}
}
}
}
for (int i = 0; i < n; i++) {
if (ignored[i]) {
swap(s[i], s[n - 1]);
for (int j = 0; j < n; j++) {
swap(cost[i][j], cost[n - 1][j]);
swap(cost[j][i], cost[j][n - 1]);
}
n--;
}
}
}
void BuildDp() {
dp.resize(1 << n, vector<int>(n, kInf));
where.resize(1 << n, vector<pii>(n));
for (int i = 0; i < n; i++) {
dp[1 << i][i] = s[i].size();
where[1 << i][i] = {0, -1};
}
for (int i = 1; i < (1 << n); i++) {
for (int j = 0; j < n; j++) {
if (dp[i][j] != kInf) {
if ((1 << j) & i) {
for (int k = 0; k < n; k++) {
if (((1 << k) & i) == 0) {
if (dp[i][j] + cost[j][k] < dp[i + (1 << k)][k]) {
dp[i + (1 << k)][k] = dp[i][j] + cost[j][k];
where[i + (1 << k)][k] = {i, j};
}
}
}
}
}
}
}
}
void Print(int i, int j) {
if (i == 0) {
return;
}
Print(where[i][j].fi, where[i][j].se);
int last = where[i][j].se;
int curr = j;
if (last == -1) {
fout << s[curr];
} else {
for (int k = s[curr].size() - cost[last][curr]; k < s[curr].size(); k++) {
fout << s[curr][k];
}
}
}
void PrintAnswer() {
int ans = kInf;
int x, y;
for (int i = 0; i < n; i++) {
if (dp[(1 << n) - 1][i] < ans) {
ans = dp[(1 << n) - 1][i];
x = (1 << n) - 1;
y = i;
}
}
Print(x, y);
}
int main() {
Read();
BuildGraph();
BuildDp();
PrintAnswer();
return 0;
}