Pagini recente » Cod sursa (job #2701933) | Cod sursa (job #1899154) | Cod sursa (job #2174512) | Cod sursa (job #2043066) | Cod sursa (job #1580643)
#include <fstream>
#include <string>
#include <vector>
using namespace std;
ifstream fin ("adn.in");
ofstream fout ("adn.out");
int n, D[30010], Cost[20][20], C[20][(1 << 18) + 10], Dad[20][(1 << 18) + 10];
string S[20];
bool F[20];
vector < int > Sol;
int KMP(string &A, string &B)
{
int k = 0;
for (int i = 1; i < A.size(); i ++)
{
while (k && A[i] != A[k]) k = D[k - 1];
if (A[i] == A[k]) k ++;
D[i] = k;
}
k = 0;
for (int i = 0; i < B.size(); i ++)
{
while (k && B[i] != A[k]) k = D[k - 1];
if (B[i] == A[k]) k ++;
}
return k;
}
bool Verif(string &A, string &B)
{
int k = 0;
for (int i = 1; i < A.size(); i ++)
{
while (k && A[i] != A[k]) k = D[k - 1];
if (A[i] == A[k]) k ++;
D[i] = k;
}
k = 0;
for (int i = 0; i < B.size(); i ++)
{
while (k && B[i] != A[k]) k = D[k - 1];
if (B[i] == A[k]) k ++;
if (k == A.size())
{
return true;
}
}
return false;
}
int main()
{
fin >> n;
for (int i = 1; i <= n; i ++) fin >> S[i];
/// Daca se cuprinde vreun cuvant in altul
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= n; j ++)
{
if (i == j || F[i] || F[j]) continue;
if (S[i].size() <= S[j].size())
{
if (Verif(S[i], S[j])) F[i] = true;
}
}
}
/// Elimin cuvintele cuprinse in altele
for (int i = 1; i <= n; i ++)
{
while (F[i] && i <= n)
{
swap(F[i], F[n]);
swap(S[i], S[n]);
n --;
}
}
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= n; j ++)
{
if (i == j) continue;
Cost[i - 1][j - 1] = KMP(S[j], S[i]); /// cel mai lung sufix al cuvantului i care este prefix al cuvantului j
}
}
/// ciclu hamiltonian de cost maxim j find nodul de inceput adaugandul de fiecare data
for (int mask = 0; mask < (1 << n); mask ++)
{
for (int j = 0; j < n; j ++)
{
Dad[j][mask] = -1;
if (mask & (1 << j))
{
for (int k = 0; k < n; k ++)
{
if (mask & (1 << k))
{
if (C[k][mask ^ (1 << j)] + Cost[j][k] > C[j][mask])
{
C[j][mask] = C[k][mask ^ (1 << j)] + Cost[j][k];
Dad[j][mask] = k;
}
}
}
}
}
}
/// Cautam nodul de start
int sum = 0, nod = 0;
for (int i = 0; i < n; i ++)
{
if (C[i][(1 << n) - 1] > sum)
{
sum = C[i][(1 << n) - 1];
nod = i;
}
}
/// Cautam lantul de cost maxim si lungine minima
int mask = (1 << n) - 1, next_nod;
while (nod > -1)
{
Sol.push_back(nod + 1);
next_nod = Dad[nod][mask];
mask -= (1 << nod);
nod = next_nod;
}
/// Afisam solutia
fout << S[Sol.front()];
nod = Sol.front();
for (int i = 1; i < Sol.size(); i ++)
{
int de_unde = Cost[nod - 1][Sol[i] - 1];
//S[Sol[i]].erase(0, de_unde);
fout << S[Sol[i]].substr(de_unde);
nod = Sol[i];
}
fout.close();
return 0;
}