Pagini recente » Cod sursa (job #2085823) | Cod sursa (job #32415) | Cod sursa (job #2256817) | Cod sursa (job #1430498) | Cod sursa (job #2764699)
#include <fstream>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
char s[20][30005];
int n;
vector<int> a[20];
void read() {
int i;
ifstream f("adn.in");
f >> n;
for (i = 1; i <= n; i++)
f >> s[i];
f.close();
}
bool eliminat[20];
int tabel[30005];
int cost[(1 << 20)][20];
int pre[(1 << 20)][20];
int comun[20][20];
vector<int> reconst;
void solve() {
int i, j, ind1, ind2, lung1, lung2, k, ok;
// kmp sa elimin sirurile care sunt in alte siruri O(n^2 * (lung1 + lung2))
for (i = 1; i <= n; i++)
if (!eliminat[i])
for (j = 1; j <= n; j++)
if (i != j && !eliminat[j]) {
ind1 = 0, ind2 = 1, lung1 = strlen(s[i]), lung2 = strlen(s[j]);
for (k = 0; k < lung1; k++)
tabel[k] = 0;
while (ind2 < lung1) {
if (s[i][ind1] == s[i][ind2]) {
tabel[ind2] = ind1 + 1;
ind1++, ind2++;
}
else if (ind1 != 0)
ind1 = tabel[ind1 - 1];
else ind2++;
}
ok = 0;
ind1 = 0;
for (ind2 = 0; ind2 < lung2;) {
if (s[i][ind1] == s[j][ind2])
ind1++, ind2++;
else if (ind1 != 0)
ind1 = tabel[ind1 - 1];
else ind2++;
if (ind1 == lung1) {
ok = 1;
break;
}
}
if (ok)
eliminat[i] = 1;
}
int l = 0;
for (i = 1; i <= n; i++)
if (!eliminat[i]) {
strcpy(s[++l], s[i]);
}
n = l;
// asociem cuvintelor un graf ponderat, in care costul reprezinta cel mai lung sufix din i care este prefix in j (tot cu KMP)
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
if (i != j) {
ind1 = 0, ind2 = 1, lung1 = strlen(s[i]), lung2 = strlen(s[j]);
for (k = 0; k < lung2; k++)
tabel[k] = 0;
while (ind2 < lung2) {
if (s[j][ind1] == s[j][ind2]) {
tabel[ind2] = ind1 + 1;
ind1++, ind2++;
}
else if (ind1 != 0)
ind1 = tabel[ind1 - 1];
else ind2++;
}
ind1 = 0;
for (ind2 = 0; ind2 < lung1; ) {
if (s[j][ind1] == s[i][ind2])
ind1++, ind2++;
else if (ind1 != 0)
ind1 = tabel[ind1 - 1];
else ind2++;
}
a[i].push_back(j);
comun[i][j] = ind1;
}
// cel mai mare lant hamiltonian (dinamica pe stari exponentiale)
int new_mask, Max, last;
for (i = 0; i < (1 << n); i++)
for (j = 1; j <= n; j++)
if (i & (1 << (j - 1)))
for (int x: a[j])
if (!(i & (1 << (x - 1)))) {
new_mask = i + (1 << (x - 1));
if (cost[new_mask][x] < cost[i][j] + comun[j][x]) {
cost[new_mask][x] = max(cost[new_mask][x], cost[i][j] + comun[j][x]);
pre[new_mask][x] = j;
}
if (cost[new_mask][x] > Max) {
Max = cost[new_mask][x];
last = x;
}
}
// reconstituire
if (n == 1)
reconst.push_back(n);
else {
int mask, node, nr;
reconst.emplace_back(last);
mask = (1 << n) - 1;
if (n >= 2)
while (true) {
node = pre[mask][last];
reconst.push_back(node);
mask = mask - (1 << (last - 1));
last = node;
nr = 0;
for (i = 1; i <= n; i++)
if (mask & (1 << (i - 1)))
nr++;
if (nr == 1)
break;
}
}
// afisez rezultatul
int lung;
ofstream g("adn.out");
for (i = reconst.size() - 1; i >= 1; i--) {
lung = strlen(s[reconst[i]]);
for (j = 0; j < lung - comun[reconst[i]][reconst[i - 1]]; j++)
g << s[reconst[i]][j];
}
g << s[reconst[0]];
g.close();
}
int main() {
read();
solve();
return 0;
}