Pagini recente » Cod sursa (job #2830487) | Cod sursa (job #2878680) | Cod sursa (job #2094383) | Cod sursa (job #1092777) | Cod sursa (job #2964408)
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
const int INF = (1 << 30);
vector <int> kmp(string s, string t) {
string w = s + "$" + t;
vector <int> pi(w.size(), 0);
for (int i = 1, k = 0; i < w.size(); ++i) {
while (k > 0 && w[i] != w[k])
k = pi[k - 1];
if (w[i] == w[k])
++k;
pi[i] = k;
}
return pi;
}
bool isSubstring(string s, string t) {
vector <int> pi = kmp(s, t);
return find(pi.begin(), pi.end(), s.size()) != pi.end();
}
int main() {
ifstream fin("adn.in");
ofstream fout("adn.out");
int N;
fin >> N;
vector <string> input_words(N);
for (int i = 0; i < N; ++i) {
fin >> input_words[i];
}
// remove duplicates
vector <string> words;
sort(input_words.begin(), input_words.end());
for (int i = 0, j = 0; i < input_words.size(); i = j) {
while (j < input_words.size() && input_words[i] == input_words[j]) {
++j;
}
words.push_back(input_words[i]);
}
input_words = words;
words.clear();
//remove useless words (words that are substrings of other words)
N = input_words.size();
for (int i = 0; i < N; ++i) {
bool ok = true;
for (int j = 0; j < N && ok; ++j) {
if (i != j && isSubstring(input_words[i], input_words[j])) {
ok = false;
}
}
if (ok) {
words.push_back(input_words[i]);
}
}
/*for (auto& i : words) {
cerr << i << "\n";
}*/
N = words.size();
vector <vector <int>> cost(N, vector <int>(N, 0));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
if (i != j) {
cost[i][j] = kmp(words[i], words[j]).back();
}
}
}
vector <vector <int>> dp(N, vector <int>((1 << N), -INF));
vector <vector <pair <int, int>>> prev(N, vector <pair <int, int>>((1 << N)));
for (int i = 0; i < N; ++i) {
dp[i][1 << i] = 0;
prev[i][1 << i] = { -1, 0 };
}
for (int mask = 1; mask < (1 << N); ++mask) {
for (int i = 0; i < N; ++i) {
if (mask & (1 << i)) {
for (int j = 0; j < N; ++j) {
if (!(mask & (1 << j))) {
int new_mask = mask | (1 << j);
if (dp[i][mask] + cost[j][i] > dp[j][new_mask]) {
dp[j][new_mask] = dp[i][mask] + cost[j][i];
prev[j][new_mask] = { i, mask };
}
}
}
}
}
}
int best = -INF;
int pos = -1;
for (int i = 0; i < N; ++i) {
if (dp[i][(1 << N) - 1] > best) {
best = dp[i][(1 << N) - 1];
pos = i;
}
}
vector <int> words_order;
int mask = (1 << N) - 1;
while (pos != -1) {
//cerr << pos << " " << mask << "\n";
words_order.push_back(pos);
int new_pos = prev[pos][mask].first;
mask = prev[pos][mask].second;
pos = new_pos;
}
reverse(words_order.begin(), words_order.end());
/*for (auto& i : words_order) {
cerr << words[i] << "\n";
}*/
string answer = words[words_order[0]];
for (int i = 1; i < N; ++i) {
int c = cost[words_order[i]][words_order[i - 1]];
/*cerr << c << "\n";*/
answer += words[words_order[i]].substr(c);
}
fout << answer << "\n";
fin.close();
fout.close();
return 0;
}