Pagini recente » Cod sursa (job #661477) | Cod sursa (job #884966)
Cod sursa(job #884966)
//O prima observatie la problema e ca daca avem cuvinte incluse in alte cuvinte, acelea nu ne mai intereseaza
//Formam un graf, nodurile fiind reprezentate de sirurile din input, iar muchiile cu cost = cat se suprapun cele 2 siruri
//Aflam un lant hamiltonian de cost maxim cu dinamica
//Dp[Conf][i] - costul maxim al unui lant hamiltonian care trece prin nodurile marcate cu 1 in conf si se termina in i
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define Nmax 19
#define Lmax 30010
#define Inf 0x3f3f3f3f
int N, AnsConf, Dp[1 << Nmax][Nmax], PI[Nmax][Lmax];
int Overlap[Nmax][Nmax], Sz[Nmax], Prev[1 << Nmax][Nmax];
bool Out[Nmax];
char S[Nmax][Lmax];
ifstream in("adn.in");
ofstream out("adn.out");
void Build_Prefix(int Idx)
{
int i, Q = 0;
PI[Idx][1] = 0;
for(i = 2; i <= Sz[Idx]; ++ i)
{
while(Q && S[Idx][Q + 1] != S[Idx][i]) Q = PI[Idx][Q];
if(S[Idx][Q + 1] == S[Idx][i]) Q ++;
PI[Idx][i] = Q;
}
}
int GetOverlap(int A, int B)
{
int i, Q = 0;
for(i = 1; i <= Sz[A]; ++ i)
{
while(Q && S[B][Q + 1] != S[A][i]) Q = PI[B][Q];
if(S[B][Q + 1] == S[A][i]) Q ++;
if(Q == Sz[B])
return Q;
}
return Q;
}
void Reconstruct(int Conf, int Pos)
{
if(Conf == (1 << Pos))
{
out << S[Pos] + 1;
return ;
}
Reconstruct(Conf ^ (1 << Pos), Prev[Conf][Pos]);
out << S[Pos] + 1 - Overlap[Prev[Conf][Pos]][Pos];
}
int main()
{
in >> N;
for(int i = 0; i < N; ++ i)
{
in >> (S[i] + 1);
Sz[i] = strlen(S[i] + 1);
Build_Prefix(i);
}
for(int i = 0; i < N; ++ i)
for(int j = i + 1; j < N; ++ j)
{
int FirstOver = GetOverlap(i, j), SecondOver = GetOverlap(j, i);
Overlap[i][j] = -FirstOver;
Overlap[j][i] = -SecondOver;
if(FirstOver == Sz[j]) Out[j] = 1;
if(SecondOver == Sz[i] && FirstOver != Sz[j]) Out[i] = 1;
}
memset(Dp, Inf, sizeof(Dp));
for(int i = 0; i < N; ++ i)
if(Out[i] == 0)
{
Dp[1 << i][i] = 0;
AnsConf ^= (1 << i);
}
for(int Conf = 1; Conf < (1 << N); ++ Conf)
for(int i = 0; i < N; i++)
if(Out[i] == 0 && Dp[Conf][i] != Inf && (Conf & (1 << i)))
for(int j = 0; j < N; j++)
if(!Out[j] && !(Conf & (1 << j)))
if(Dp[Conf ^ (1 << j)][j] > Dp[Conf][i] + Overlap[i][j])
{
Dp[Conf ^ (1 << j)][j] = Dp[Conf][i] + Overlap[i][j];
Prev[Conf ^ (1 << j)][j] = i;
}
int StartPos = 0;
for(int i = 0; i < N; i++)
if(Dp[AnsConf][i] < Dp[AnsConf][StartPos])
StartPos = i;
Reconstruct(AnsConf, StartPos);
return 0;
}