Pagini recente » IAP #6: Arhiva educationala | Borderou de evaluare (job #3201311) | IAP #6: Arhiva educationala | Cod sursa (job #3278654) | Cod sursa (job #2985474)
#include <bits/stdc++.h>
using namespace std;
#if 1
#define cin fin
#define cout fout
ifstream fin("adn.in");
ofstream fout("adn.out");
#endif // 1
const int inf = 1e7;
const int nmx = 18;
const int mskmx = 1 << nmx;
int a[nmx][nmx];
int dp[mskmx][nmx], t[mskmx][nmx];
vector<int> calcPi(const string& s) {
vector<int> pi(s.size());
int j = 0;
for (int i = 1; i < s.size(); i++) {
while (j > 0 && s[i] != s[j])
j = pi[j - 1];
if (s[i] == s[j])
j++;
pi[i] = j;
}
return pi;
}
int _conc(const string& s1,const string& s2) {
string c = s2 + s1;
vector<int> pi = calcPi(c);
return min(pi[c.size() - 1],(int)s2.size());
}
string concat(const string& s1,const string& s2) {
int r = _conc(s1,s2);
return s1 + s2.substr(r);
}
int main() {
int n;
cin >> n;
vector<string> vs(n);
for (int i = 0; i < n; i++)
cin >> vs[i];
for(int i=0;i<vs.size();i++)
for(int j=0;j<vs.size();j++)
if(i!=j)
if(vs[i].find(vs[j])!=string::npos)
vs.erase(vs.begin()+j);
n = vs.size();
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
a[i][j] = concat(vs[i],vs[j]).size() - vs[i].size();
for (int msk = 0; msk < mskmx; msk++)
for (int i = 0; i < n; i++)
dp[msk][i] = inf,t[msk][i] = -1;
// calculate expo dp
for (int i = 0; i < n; i++)
dp[1 << i][i] = vs[i].size();
int mskn = (1 << n);
for (int msk = 0; msk < mskn; msk++) {
for (int i = 0; i < n; i++) {
if (msk & (1 << i)) {
for (int j = 0; j < n; j++) {
if (msk & (1 << j)) {
int nv = dp[msk ^ (1 << i)][j] + a[j][i];
if (dp[msk][i] > nv) {
dp[msk][i] = nv;
t[msk][i] = j;
}
}
}
}
}
}
// get minimum
int mn = INT_MAX, mni;
for (int i = 0; i < n; i++) {
if (mn > dp[mskn - 1][i]) {
mn = dp[mskn - 1][i];
mni = i;
}
}
// reconstruct path
int cmsk = mskn - 1;
int it = mni;
vector<int> p;
while (cmsk) {
p.push_back(it);
int ta = t[cmsk][it];
cmsk = cmsk ^ (1 << it);
it = ta;
}
// for(int i=p.size()-1;i>=0;i--)
// cout << p[i] << " ";
string res = vs[p.back()];
for (int i = p.size() - 2; i >= 0; i--){
res = concat(res, vs[p[i]]);
}
cout << res;
}