Pagini recente » Cod sursa (job #3290379) | Cod sursa (job #2673860) | Cod sursa (job #1255805) | Cod sursa (job #1513351) | Cod sursa (job #2939063)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
int N;
string s[19];
int dist[19][19];
long long dp[19][524289];
int parinte[19][524289];
bool kmp(int a1, int a2) {
string V = '0' + s[a1] + '*' + s[a2];
int n = V.size() - 1;
int nz = s[a1].size();
int pi[60004];
for(int i = 2; i <= n; i++) {
if(V[i] == V[pi[i - 1] + 1]) {
pi[i] = pi[i - 1] + 1;
}
else {
int j = pi[pi[i - 1]];
while(j > 0 && V[i] != V[j + 1]) {
j = pi[j];
}
if(V[i] == V[j + 1]) {
pi[i] = j + 1;
}
else {
if(V[i] == V[1])
pi[i] = 1;
else
pi[i] = 0;
}
}
if(pi[i] == nz && i > nz) {
return true;
}
}
return false;
}
void citire() {
fin >> N;
for(int i = 1; i <= N; i++) {
fin >> s[i];
for(int j = 1; j < i; j++) {
if(kmp(j, i)) {
for(int k = j; k < i; k++) {
s[k] = s[k+1];
}
i--;
N--;
}
if(kmp(i, j)) {
i--;
N--;
}
}
}
}
int pi[60005];
int calc_dist(int s1, int s2) {
string A = '0' + s[s1] + '*' + s[s2];
int n = A.size() - 1;
for(int i = 0; i <= n; i++) {
pi[i] = 0;
}
//incepe kmp
for(int i = 2; i <= n; i++) {
if(A[i] == A[pi[i - 1] + 1]) {
pi[i] = pi[i - 1] + 1;
}
else {
int j = pi[pi[i - 1]];
while(j > 0 && A[i] != A[j + 1]) {
j = pi[j];
}
if(A[i] == A[j + 1]) {
pi[i] = j + 1;
}
else {
if(A[i] == A[1])
pi[i] = 1;
else
pi[i] = 0;
}
}
}
return pi[n];
}
void init() {
for(int sir1 = 1; sir1 <= N; sir1++) {
for(int sir2 = 1; sir2 <= N; sir2++) {
if(sir1 != sir2) {
//se calculeaza distanta intre stringuri
dist[sir1][sir2] = calc_dist(sir2, sir1);
}
}
}
//initializam matricea de parinti
for(int i = 1; i <= N; i++) {
parinte[i][0] = -1;
}
}
void cautare() {
//parcurgem dp pe configuratii
int stop = (1 << N) - 1;
for(int i = 1; i <= stop; i++) {
//ne ducem in toate dp-urile nodurilor in care i are 1 pe pozitia corespunzatoare lui
int config = i;
for(int nod = 1; nod <= N; nod++) {
if((config & (1 << (nod - 1))) != 0) { //avem 1 pe pozitia nodului
config = config & (~(1 << (nod - 1)));//stergem 1 de pe pozitia nodului
int mx = -1, orig;
for(int y = 1; y <= N; y++) {
if(y != nod && (dp[y][config] + dist[y][nod] > mx)) {
mx = dp[y][config] + dist[y][nod];
orig = y;
}
}
dp[nod][i] = mx;
parinte[nod][i] = orig;
}
config = i;
}
}
}
int ultimul() {//rezultatul este stocat in maximul coresp ultimei coloane
int coloana = (1 << N) - 1;
int rez = 0, nod;
for(int i = 1; i <= N; i++) {
if(dp[i][coloana] > rez) {
rez = dp[i][coloana];
nod = i;
}
}
return nod;
}
string secventa = "";
void concat(int indice, int suprap) {
int y = secventa.size() - suprap;
int stop = y + s[indice].size() - 1;
for(int i = y; i <= stop; i++) {
if(i >= secventa.size())
secventa += s[indice][i - y];
else
secventa[i] = s[indice][i - y];
}
}
void calculare(int nod, int config) {
bitset<22> b(config);
int p = parinte[nod][config];
if(b.count() > 1)
calculare(p, (config) & ~(1 << (nod - 1)));
if(secventa == "") {
secventa = s[nod];
}
else {
concat(nod, dist[p][nod]);
}
}
int main() {
citire();
init();
cautare();
calculare(ultimul(), (1 << N) - 1);
fout << secventa;
return 0;
}