Pagini recente » Cod sursa (job #2673642) | Cod sursa (job #1835827) | Cod sursa (job #990534) | Cod sursa (job #1083426) | Cod sursa (job #3358143)
#include <fstream>
#include <iostream>
#include <stack>
#include <string.h>
#include <vector>
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
const int NMAX = 3e4 + 1;
const int oo = 0x3f3f3f;
int dist[20][20];
int dp[19][1 << 19];
char parent[19][1 << 19];
int overlapKMP(string &a, string &b, bool &contained)
{
string s = b + '#' + a;
int m = s.size();
vector<int> pi(m, 0);
contained = false;
for (int i = 1; i < m; ++i)
{
int k = pi[i - 1];
while (k > 0 && s[i] != s[k])
k = pi[k - 1];
if (s[i] == s[k])
++k;
pi[i] = k;
if (k == b.size())
contained = true;
}
return pi[m - 1];
}
int main()
{
int n;
fin >> n;
bool contained[20] = {false};
vector<string> sequences(n + 1);
memset(dist, oo, sizeof(dist));
for (int i = 1; i <= n; ++i)
{
fin >> sequences[i];
dist[0][i] = sequences[i].size();
}
int finalMask = (1 << (n + 1)) - 1;
for (int i = 1; i <= n; ++i)
{
if (contained[i])
continue;
for (int j = 1; j <= n; ++j)
{
if (contained[j] || i == j)
continue;
int overlap = overlapKMP(sequences[i], sequences[j], contained[j]);
if (contained[j])
finalMask = (finalMask ^ (1 << j));
else
dist[i][j] = sequences[j].size() - overlap;
}
}
memset(dp, 0x3f3f3f3f, sizeof(dp));
dp[0][1] = 0;
for (int mask = 1; mask < (1 << (n + 1)); ++mask)
{
// check if mask is a subset of finalMask
if ((mask & finalMask) != mask)
continue;
for (int j = 1; j <= n; j++)
{
if ((mask & (1 << j)) != 0)
{
int prev = mask - (1 << j);
if (prev)
{
for (int k = 0; k <= n; k++)
{
if ((prev & (1 << k)) != 0)
{
if (dp[j][mask] > dp[k][prev] + dist[k][j])
{
dp[j][mask] = dp[k][prev] + dist[k][j];
parent[j][mask] = k;
}
}
}
}
}
}
}
stack<pair<int, int>> st;
int ans = oo, last = -1;
for (int j = 1; j <= n; ++j)
if ((finalMask & (1 << j)) && dp[j][finalMask] < ans)
ans = dp[j][finalMask], last = j;
while (finalMask != 1)
{
st.push({last, ans});
int newMask = finalMask ^ (1 << last);
last = parent[last][finalMask];
ans = dp[last][newMask];
finalMask = newMask;
}
int prevLength = 0;
while (!st.empty())
{
int lastDigitsLength = st.top().second - prevLength;
fout << sequences[st.top().first].substr(sequences[st.top().first].size() - lastDigitsLength);
prevLength = st.top().second;
st.pop();
}
return 0;
}