Pagini recente » Cod sursa (job #3314121) | Cod sursa (job #927530) | Cod sursa (job #2990402) | Cod sursa (job #3327908) | Cod sursa (job #3346034)
#include <bits/stdc++.h>
#define NMAX 20
#define MMAX 524288 ///2^18
#define INF INT_MAX
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
int N;
string s[NMAX];
string s1[NMAX];
char elm[NMAX];
int c[NMAX][NMAX];
int dp[MMAX][NMAX];
pair<int,int> from[MMAX][NMAX];
string ans;
int get_cost(const string &a, const string &b)
{///cat costa sa lipim b de a (([a...][b...]))
string s = b + "#" + a;
int pi[s.length() + 2] = {0};
pi[0] = 0;
for(int i=1;i<s.length();i++){
int j = pi[i-1];
while(j > 0 && s[i] != s[j]){
j = pi[j-1];
}
if(s[i] == s[j]) j++;
pi[i] = j;
}
return b.length() - pi[s.length() - 1];
}
bool is_inside(const string &a, const string &b)
{///is a inside b?
string s = a + "#" + b;
int pi[s.length() + 2] = {0};
pi[0] = 0;
for(int i=1;i<s.length();i++){
int j = pi[i-1];
while(j > 0 && s[i] != s[j]){
j = pi[j-1];
}
if(s[i] == s[j]) j++;
pi[i] = j;
}
for(int i=a.length();i<s.length();i++){
if(pi[i] == a.length()) return 1;
}
return 0;
}
int main()
{
fin >> N;
for(int i=1;i<=N;i++){
fin >> s1[i];
}
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(i==j || elm[j]) continue;
if(is_inside(s1[i],s1[j])){
elm[i] = 1;
break;
}
}
}
int aux = 0;
for(int i=1;i<=N;i++){
if(!elm[i]) s[++aux] = s1[i];
}
N = aux;
// cout << N << "\n";
// for(int i=1;i<=N;i++){
// cout << s[i] << "\n";
// }
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(i==j) continue;
c[i][j] = get_cost(s[i], s[j]);
}
}
for(int mask = 1;mask < (1 << N);mask++){
for(int node = 1;node <=N;node++){///creca as putea ceva smecherie cu lsb, da mai vedem
if((mask & (1<<(node-1))) == 0) continue;
if(__builtin_popcount(mask) == 1){
dp[mask][node] = s[node].length();
break;
}
dp[mask][node] = INF;
for(int x = 1;x<=N;x++){
if((mask & (1<<(x-1))) == 0 || node == x) continue;
///adaugam node dp[mask fara node][x]
int len = dp[mask ^ (1<<(node-1))][x] + c[x][node];
if(len < dp[mask][node]){
from[mask][node] = {mask ^ (1<<(node-1)), x};///nu mi trb neaparat si aia cu mask, da sybau
dp[mask][node] = len;
}
}
}
}
pair <int,int> idx = {(1<<N) - 1, 1};
for(int i=1;i<=N;i++){
if(dp[(1<<N) - 1][i] < dp[idx.first][idx.second]){
idx = {(1<<N) - 1, i};
}
}
vector <int> indici;
while(idx != pair<int,int>{0,0}){
auto [i,j] = idx;
indici.push_back(j);
idx = from[i][j];
}
reverse(indici.begin(),indici.end());
ans = s[indici[0]];
for(int idx = 1;idx<indici.size();idx++){
int i = indici[idx];
int j = indici[idx-1];
///lipim s[i] la finalul lui s[j]
int cost = c[j][i];
for(int x = s[i].length() - cost; x< s[i].length(); x++){
ans.push_back(s[i][x]);
}
}
fout << ans;
}