Pagini recente » Cod sursa (job #2392495) | Cod sursa (job #1477664) | Cod sursa (job #747840) | Cod sursa (job #1716652) | Cod sursa (job #81142)
Cod sursa(job #81142)
using namespace std;
#include <stdio.h>
#include <string.h>
#include <vector>
#define Nmax 18
#define Lmax 30001
#define cardinal 1<<18
int N, i, j, ban=0, banned=0;
int T[Lmax], g[Nmax][Nmax];
int A[Nmax][cardinal],Ant[Nmax][cardinal];
char s[Nmax][Lmax];
vector<int> M[Nmax+1];
void submultimi(int nr, int card)
{
int i, p;
M[card].push_back(nr);
if (card == N - banned) return;
++card;
for (i=0,p=1; i<N; ++i,p<<=1)
if ((p ^ nr) > nr) submultimi(nr+p, card);
}
void init()
{
int i, p;
for (i=0,p=1; i<N; ++i,p<<=1)
if ((p ^ ban) > ban) submultimi(ban + p, 1);
}
void citire()
{
freopen("adn.in", "r", stdin);
scanf("%d", &N);
for (i=0; i<N; ++i)
scanf("%s", &s[i]);
fclose(stdin);
}
void prefix(int indice)
{
int i = 2, j = 0, lungime = strlen( s[indice] );
while (i <= lungime)
if (s[indice][i-1] == s[indice][j])
T[i++] = j++;
else if (j>0) j = T[j];
else T[i++] = 0;
}
int KMP(int sursa, int subsir)
{
int i = 0, j = 0, l1 = strlen( s[sursa] ), l2 = strlen( s[subsir] );
while (i + j < l1)
{
if (s[sursa][i+j] == s[subsir][j])
{
++j;
if (j == l2) {
++banned;
ban+=(1<<subsir);
return -1; //potrivire completa
}
}
else
{
i = i + j - T[j];
if (j > 0) j = T[j];
}
}
return j; //ultimele j caractere din sursa corespund primelor j din subsir
}
void hamiltonian_cycle()
{
vector<int>::iterator it;
int i, j, p, jj, pp;
//programare dinamica
for (i=0,p=1; i<N; ++i,p<<=1)
if ((p^ban)>ban)
{
A[i][p^ban]=1;
Ant[i][p^ban]=-1;
}
for (i=1; i<N-banned; ++i)
for (it=M[i].begin(); it<M[i].end(); ++it)
for (j=0,p=1; j<N; ++j,p<<=1)
if ((p ^ (*it - ban)) < (*it - ban))
for (jj=0,pp=1; jj<N; ++jj,pp<<=1)
if ( ((pp ^ (*it)) > *it) && (A[jj][pp ^ *it] < A[j][*it] + g[j][jj]) )
{
A[jj][pp ^ *it] = A[j][*it] + g[j][jj];
Ant[jj][pp ^ *it] = j;
}
}
void solutie()
{
int i, max, p = (1<<N)-1, pp;
max=0;
for (i=1; i<N; ++i)
if (A[i][p] > A[max][p]) max = i;
freopen("adn.out","w",stdout);
while (Ant[max][p] != -1)
{
pp = strlen(s[max]) - g[Ant[max][p]][max];
for (i=0; i<pp; ++i)
printf("%c", s[max][i]);
pp = p;
p -= (1 << max);
max = Ant[max][pp];
}
printf("%s",s[max]);
fclose(stdout);
}
int main()
{
citire();
T[0] = -1;
T[1] = 0;
//muchiile sunt retinute in sens invers ca sa nu rup linia de cache cu for-u
//g[i][j] = costul arcului de la j la i
//astfel rezultatul va fi afisat in ordine inversa dupa indici
for (i=0; i<N; ++i)
{
prefix(i);
for (j=0; j<i; ++j)
g[i][j] = KMP(j, i);
for (j=i+1; j<N; ++j)
g[i][j] = KMP(j, i);
}
init();
hamiltonian_cycle();
solutie();
return 0;
}