Pagini recente » Cod sursa (job #3244800) | Cod sursa (job #144233) | Cod sursa (job #3257969) | Cod sursa (job #2176886) | Cod sursa (job #3239266)
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <unordered_map>
#include <climits>
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
const int LMAX = 30005;
const int INF = 0x3f3f3f3f;
int pi[20][LMAX], dp[(1<<18)][20], cost[20][20], n, from[(1<<18)][20];
char a[20][LMAX];
bool notok[20];
void Pi(char* s, int pos) {
int k = 0, n = strlen(s + 1);
for (int i = 2; i <= n; i++) {
while (k && s[k + 1] != s[i]) {
k = pi[pos][k];
}
if (s[k + 1] == s[i]) k++;
pi[pos][i] = k;
}
}
int calc(int x, int y) {
if (x == y) {
return -INF;
}
int k = 0, m = strlen(a[y] + 1), z = strlen(a[x] + 1);
for (int i = 1; i <= m; i++) {
while (k && a[x][k + 1] != a[y][i]) {
k = pi[x][k];
}
if (a[x][k + 1] == a[y][i]) {
k++;
}
if (k == z) { //s a regasit total cuvantul x
notok[x] = 1;
return -INF;
}
}
return k;
}
//void reconst(int mask, int nxt) {
// if (mask) {
// int last;
// for (int i = 0; i < n; i++) {
// if (dp[mask][i] + cost[i][nxt] == ans - rest) {
// last = i;
// }
// }
// rest+=cost[last][nxt];
// reconst((mask^(1<<last)), last);
// if ((mask&(mask - 1))) {
// //a mai ramas un bit
// prv = last;
// fout<<a[prv] + 1;
// }
// else {
// fout<<a[last] + 1 + cost[prv][last];
// prv = last;
// }
// }
//}
//vreau sa ignor total anumite cuvinte
void reconst2(int mask, int last) {
if (mask) {
reconst2((mask^(1<<last)), from[mask][last]);
if ((mask&(mask - 1)) == 0) {
fout<<a[last] + 1;
}
else {
fout<<a[last] + 1 + cost[from[mask][last]][last];
}
}
}
int main() {
int i, j;
fin>>n;
fin.get();
for (i = 0; i < n; i++) {
fin.get(a[i] + 1, LMAX);
fin.get();
Pi(a[i], i);
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
//calculez costul
cost[i][j] = calc(j, i); //pun j la capatul lui i
}
}
int mask, tot;
tot = 0;
for (i = 0; i < n; i++) {
if (!notok[i]) {
tot += (1<<i);
}
}
for (i = 0; i <= tot; i++) {
for (j = 0; j < n; j++) {
dp[i][j] = INF;
}
}
for (i = 0; (1<<i) <= tot; i++) {
if (!notok[i]) { //daca o iau in seama
dp[(1<<i)][i] = strlen(a[i] + 1);
}
}
//vreau ca la final in masca sa ma costul maxim
for (mask = 1; mask <= tot; mask++) {
for (i = 0; (1<<i) <= mask; i++) {
if ((mask&(1<<i)) && !notok[i]) {
for (j = 0; (1<<j) <= mask; j++) {
if (i != j && (mask&(1<<j)) && !notok[j]) {
if (dp[(mask^(1<<i))][j] + strlen(a[i] + 1) - cost[j][i] < dp[mask][i]) {
dp[mask][i] = dp[(mask^(1<<i))][j] + strlen(a[i] + 1) - cost[j][i];
from[mask][i] = j;
}
}
}
}
}
}
mask--;
int ans = INF;
int last;
for (i = 0; i < n; i++) {
if (ans > dp[mask][i]) {
ans = dp[mask][i];
last = i;
}
}
reconst2(mask, last);
// reconst((mask^(1<<last)), last);
fin.close();
fout.close();
return 0;
}