Pagini recente » Cod sursa (job #3185145) | Cod sursa (job #3150025) | Cod sursa (job #1193899) | Cod sursa (job #1309630) | Cod sursa (job #773500)
Cod sursa(job #773500)
#include <fstream>
#include <string>
#include <climits>
#include <algorithm>
#define INFILE "adn.in"
#define OUTFILE "adn.out"
#define NMAX 18
#define SMAX 30001
#define EMAX 262999
using namespace std;
int N;
string S[SMAX];
int Size[NMAX];
bool L[NMAX];
int Mch[NMAX][NMAX];
int Min[NMAX][EMAX];
int Whi[NMAX][EMAX];
void computePrefix(string S, int size, int Pi[])
{
int i, k;
for (i = 1; i <= size; ++i)
{
Pi[i] = 0;
}
// functia prefix
for (i = 2; i <= size; ++i)
{
k = Pi[i - 1];
while (k > 0 && S[k + 1] != S[i])
{
k = Pi[k];
}
if (S[k + 1] == S[i])
{
++k;
}
Pi[i] = k;
}
}
bool getMatch(string T, int Tsize, string X, int Xsize, int Pi[])
{
int i, k;
// functia potrivire
for (i = 1, k = 0; i <= Tsize; ++i)
{
while (k > 0 && X[k + 1] != T[i])
{
k = Pi[k];
}
if (X[k + 1] == T[i])
{
++k;
}
if (k == Xsize)
{
return true;
}
}
return false;
}
bool firstContainsSecond(int t, int x)
{
if (Size[t] < Size[x])
{
return false;
}
int i, k;
int Pi[SMAX];
computePrefix(S[x], Size[x], Pi);
return getMatch(S[t], Size[t], S[x], Size[x], Pi);
}
int computePrefixSuffix(int x, int y)
{
string T = " " + S[x].substr(1, Size[x]) + S[y].substr(1, Size[y]);
int Tsize = Size[x] + Size[y];
int i, k;
int Pi[SMAX + SMAX];
computePrefix(T, Tsize, Pi);
int mini = min(Size[x], Size[y]);
while (Pi[Tsize] > mini)
{
Tsize = Pi[Tsize];
}
return Pi[Tsize];
}
void eliminateInclusions()
{
int i, j;
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
if (i == j)
{
continue;
}
if (firstContainsSecond(j, i))
{
if (Size[j] != Size[i] || i < j)
{
L[i] = true;
}
}
}
}
for (i = j = 0; i < N && j < N; ++i, ++j)
{
while (L[j])
{
++j;
}
S[i] = S[j];
Size[i] = Size[j];
}
N = i;
}
void computePrefixesSuffixes()
{
int i, j;
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
if (i == j)
{
continue;
}
Mch[i][j] = computePrefixSuffix(i, j);
}
}
}
void computeHamiltonians()
{
int i, j, k, l, v;
// Do the steps for singular words
for (i = 0; i < N; ++i)
{
Min[i][1 << i] = Size[i];
Whi[i][1 << i] = INT_MAX;
}
// Do the steps for bigger numbers
for (k = 1; k < (1 << N); ++k)
{
for (i = 0; i < N; ++i)
{
if (!(k ^ (1 << i)))
{
continue;
}
Min[i][k] = Whi[i][k] = INT_MAX;
if (!(k & (1 << i)))
{
continue;
}
l = k ^ (1 << i);
for (j = 0; j < N; ++j)
{
if (i == j || !(k & (1 << j)))
{
continue;
}
v = Min[j][l] + Size[i] - Mch[i][j];
if (v < Min[i][k])
{
Min[i][k] = v;
Whi[i][k] = j;
}
}
}
}
}
string computeMinString()
{
int i, j, k;
string T = "";
int min = INT_MAX;
int sta = INT_MAX;
for (i = 0; i < N; ++i)
{
if (Min[i][(1 << N) - 1] < min)
{
min = Min[i][(1 << N) - 1];
sta = i;
}
}
for (i = sta, k = (1 << N) - 1; i != INT_MAX; k = k ^ (1 << i), i = j)
{
j = Whi[i][k];
if (j == INT_MAX)
{
T = T + S[i];
}
else
{
T = T + S[i].substr(0, Size[i] - Mch[i][j]);
}
}
std::reverse(T.begin(), T.end());
return T;
}
void readWords()
{
int i;
ifstream fin(INFILE);
fin >> N;
for (i = 0; i < N; ++i)
{
fin >> S[i];
Size[i] = S[i].size();
S[i] = " " + S[i];
}
fin.close();
}
void writeConcatenation()
{
int i;
for (i = 0; i < N; ++i)
{
S[i] = S[i].substr(1, Size[i]);
std::reverse(S[i].begin(), S[i].end());
}
ofstream fout(OUTFILE);
fout << computeMinString() << endl;
fout.close();
}
int main()
{
readWords();
eliminateInclusions();
computePrefixesSuffixes();
computeHamiltonians();
writeConcatenation();
return 0;
}