Pagini recente » Cod sursa (job #2248281) | Cod sursa (job #2459460) | Cod sursa (job #3157432) | Cod sursa (job #2459461) | Cod sursa (job #2962782)
#include <bits/stdc++.h>
using namespace std;
ifstream f("adn.in");
ofstream g("adn.out");
const int NMAX = 18;
const int LMAX = 30001;
int N;
vector<string> words;
vector<vector<int>> cost, dp, prevs;
void read(){
f >> N;
words.resize(N);
for(int i = 0; i < N; ++i)
f >> words[i];
}
vector<int> GetPi(string& s){
int len = s.size();
vector<int> pi(len + 1, -1);
for(int i = 0; i < len; ++i){
int j = pi[i];
while(j != -1 && s[i] != s[j])
j = pi[j];
pi[i + 1] = j + 1;
}
return pi;
}
vector<string> preprocess(vector<string>& words){
vector<string> aux;
for(int i = 0; i < N; ++i){
auto pi = GetPi(words[i]);
bool matched = false;
for(int j = 0; j < N; ++j){
// KMP
if(i == j)
continue;
int index = 0;
for(int k = 0; words[j][k] != NULL; ++k){
while(index != -1 && words[j][k] != words[i][index])
index = pi[index];
++index;
if(index == words[i].size()){
matched = true;
break;
}
}
if(matched)
break;
}
if(!matched)
aux.push_back(words[i]);
}
return aux;
}
int GetCost(string a, string b){
auto pi = GetPi(b);
int index = 0;
for(auto x : a){
while(index != -1 && b[index] != x)
index = pi[index];
index += 1;
}
return index;
}
void solve(){
vector<string> str = preprocess(words);
N = str.size();
cost.assign(N + 1, vector<int>(N + 1, -1));
for(int i = 0; i < N; ++i)
for(int j = 0; j < N; ++j)
if(i != j)
cost[i][j] = GetCost(str[i], str[j]);
dp.assign(N + 2, vector<int>((1 << N) + 2, 0));
prevs.assign(N + 2, vector<int>((1 << N) + 2, 0));
for(int mask = 0; mask < (1 << N); ++mask){
for(int i = 0; i < N; ++i){
if(!(mask & (1 << i)))
continue;
for(int j = 0; j < N; ++ j){
if(i == j)
continue;
if(!(mask & (1 << j)))
continue;
int ct = dp[j][mask ^ (1 << i)] + cost[j][i];
if(dp[i][mask] <= ct){
dp[i][mask] = ct;
prevs[i][mask] = j;
}
}
}
}
int node = 0;
for(int i = 0; i < N; ++i)
if(dp[node][(1 << N) - 1] < dp[i][(1 << N) - 1])
node = i;
vector<int> path;
int mask = (1 << N) - 1;
while(mask){
path.push_back(node);
int prev_mask = mask ^ (1 << node);
int prev_node = prevs[node][mask];
node = prev_node;
mask = prev_mask;
}
reverse(path.begin(), path.end());
int skip_next = 0;
for(int i = 0; i < N ; ++i){
int node = path[i];
string s = str[node].substr(skip_next);
g << s;
if(i != N - 1){
skip_next = cost[node][path[i + 1]];
}
}
}
int main(){
read();
solve();
return 0;
}