Pagini recente » Borderou de evaluare (job #1359096) | Borderou de evaluare (job #2758963) | Cod sursa (job #1988317) | Cod sursa (job #2305365) | Cod sursa (job #2165273)
#include <fstream>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 18;
const int MAXL = 3e4;
const int INF = 0x3f3f3f3f;
string w[MAXN], v[MAXN];
int in[MAXN][MAXN], cost[MAXN][MAXN], dp[MAXN][1 << MAXN], pi[2 * MAXL + 3], prv[MAXN][1 << MAXN];
int contains(string& big, string& small) {
if (big.size() == small.size() && big == small)
return 1;
if (big.size() < small.size())
return 0;
int k = 0;
memset(pi, 0, sizeof pi);
for (int i = 2; i <= (int) small.size(); ++i) {
for (k = k; k > 0 && small[i - 1] != small[k]; k = pi[k]) {}
pi[i] = (k += (small[i - 1] == small[k]));
}
k = 0;
for (int i = 1; i <= (int) big.size(); ++i) {
for (k = k; k > 0 && small[k] != big[i - 1]; k = pi[k]) {}
if ((k += small[k] == big[i - 1]) == (int) small.size())
return 1;
}
return 0;
}
inline int to_add(string& a, string& b) {
string s = b + '$' + a;
memset(pi, 0, sizeof pi);
int k = 0;
for (int i = 2; i <= (int) s.size(); ++i) {
for (k = k; k > 0 && s[i - 1] != s[k]; k = pi[k]) {}
pi[i] = (k += (s[i - 1] == s[k]));
}
return (int) b.size() - pi[s.size()];
}
int main()
{
int n, m = 0;
ifstream fin("adn.in");
fin >> n;
for (int i = 0; i < n; ++i)
fin >> w[i];
fin.close();
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
in[i][j] = contains(w[j], w[i]);
for (int i = 0; i < n; ++i) {
int ok = 1;
for (int j = 0; j < n; ++j)
if ((in[i][j] == 0 || in[i][j] && in[j][i] && i <= j) == 0)
ok = 0;
if (ok)
v[m++] = w[i];
}
memset(dp, INF, sizeof dp);
memset(prv, -1, sizeof prv);
for (int i = 0; i < m; ++i) {
for (int j = 0; j < m; ++j)
cost[i][j] = to_add(v[i], v[j]);
dp[i][1 << i] = (int) v[i].size();
prv[i][1 << i] = i;
}
for (int conf = 3; conf < (1 << m); ++conf)
if (conf & (conf - 1))
for (int lst = 0; lst < m; ++lst)
if (conf & (1 << lst))
for (int p = 0; p < m; ++p)
if ((p ^ lst) && (conf & (1 << p)) && dp[p][conf ^ (1 << lst)] + cost[p][lst] < dp[lst][conf]) {
dp[lst][conf] = dp[p][conf ^ (1 << lst)] + cost[p][lst];
prv[lst][conf] = p;
}
int ind = 0, cnf = (1 << m) - 1;
for (int i = 1; i < m; ++i)
if (dp[i][cnf] < dp[ind][cnf])
ind = i;
vector <int> sol;
while (prv[ind][cnf] != -1) {
sol.push_back(ind);
int aux = prv[ind][cnf];
cnf ^= (1 << ind);
ind = aux;
}
reverse(sol.begin(), sol.end());
ofstream fout("adn.out");
fout << v[sol[0]];
for (int i = 1; i < m; ++i)
for (int j = (int) v[sol[i]].size() - cost[sol[i - 1]][sol[i]]; j < (int) v[sol[i]].size(); ++j)
fout << v[sol[i]][j];
fout.close();
return 0;
}