Pagini recente » Cod sursa (job #3347862) | Monitorul de evaluare | Monitorul de evaluare | Cod sursa (job #3333492) | Cod sursa (job #3327554)
#include <bits/stdc++.h>
#define ll long long
#define cin fin
#define cout fout
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
const int NMAX = 18;
const int INF = 2e9;
const int BASE = 37;
const int MOD = 1e9 + 9;
const int SMAX = 3e4;
int n, answer, ind;
int x[NMAX + 1];
string answer_s;
string a[NMAX + 1];
string b[NMAX + 1];
int cost[NMAX + 1][NMAX + 1];
int prefix_hash[NMAX + 1][SMAX + 1];
int pbase[SMAX + 1];
int get_hash(int h[], int left, int right) {
return (h[right] - (ll) h[left - 1] * pbase[right - left + 1] % MOD + MOD) % MOD;
}
int get_cost(string& s1, string& s2) {
int r = s1.size() - 1, l = 0;
int hs1 = 0, hs2 = 0, pbase = 1, maxi = 0;
while(l < (int) s2.size() && r >= 0) {
hs1 = (hs1 + (ll) pbase * (s1[r] - 'A' + 1)) % MOD;
hs2 = ((ll) hs2 * BASE + (s2[l] - 'A' + 1)) % MOD;
l++;
r--;
pbase = (ll) pbase * BASE % MOD;
if(hs1 == hs2) {
maxi = l;
}
}
return s2.size() - maxi;
}
bool is_substring(int i, int j) {
int sz = a[i].size();
for(int pos = sz; pos <= a[j].size(); pos++) {
if(get_hash(prefix_hash[j], pos - sz + 1, pos) == prefix_hash[i][sz]) {
return true;
}
}
return false;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
pbase[0] = 1;
for(int i = 1; i <= SMAX; i++) {
pbase[i] = (ll) pbase[i - 1] * BASE % MOD;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= a[i].size(); j++) {
prefix_hash[i][j] = ((ll) prefix_hash[i][j - 1] * BASE + (a[i][j - 1] - 'A' + 1)) % MOD;
}
}
for(int i = 1; i <= n; i++) {
bool ok = true;
for(int j = 1; j <= n; j++) {
if(i != j && is_substring(i, j)) {
ok = false;
}
}
if(ok) {
b[++ind] = a[i];
}
}
for(int i = 1; i <= ind; i++) {
a[i] = b[i];
}
n = ind;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(i != j) {
cost[i][j] = get_cost(a[i], a[j]);
}
}
}
for(int i = 1; i <= n; i++) {
x[i] = i;
}
answer = INF;
do {
int cost_here = a[x[1]].size();
string here = a[x[1]];
for(int i = 2; i <= n; i++) {
cost_here += cost[x[i - 1]][x[i]];
int pos_start = a[x[i]].size() - cost[x[i - 1]][x[i]];
here += a[x[i]].substr(pos_start, cost[x[i - 1]][x[i]]);
}
if(cost_here < answer) {
answer = cost_here;
answer_s = here;
}
}while(next_permutation(x + 1, x + n + 1));
cout << answer_s << '\n';
return 0;
}