Pagini recente » Cod sursa (job #459759) | Cod sursa (job #3345980) | Cod sursa (job #3349893) | Cod sursa (job #3319072) | Cod sursa (job #3353337)
#include <fstream>
#include <iostream>
using namespace std;
#define int long long
ifstream in("adn.in");
ofstream out("adn.out");
int n;
string s[20];
int useless[20];
int cost[20][20];
signed dp[20][262155];
signed last[20][262155];
string ans;
int lps[30005];
int INF = (1 << 30);
void build_lps(int ind)
{
for(int i = 0; i<s[ind].size(); i++)
{
lps[i] = 0;
}
int i = 1;
int j = 0;
while(i < s[ind].size())
{
if(s[ind][i] == s[ind][j])
{
j++;
lps[i] = j;
i++;
}
else
{
if(j == 0)
{
i++;
}
else
{
j = lps[j - 1];
}
}
}
}
int contains_secv(int x, int y)
{
if(s[y].size() > s[x].size())
{
return 0;
}
build_lps(y);
int i = 0;
int j = 0;
while(i < s[x].size())
{
if(s[x][i] == s[y][j])
{
i++;
j++;
if(j == s[y].size())
{
return 1;
}
}
else
{
if(j == 0)
{
i++;
}
else
{
j = lps[j - 1];
}
}
}
return 0;
}
int same_pref_suf(int x, int y) //x e concatenat cu y
{
build_lps(y);
int i = 0;
int j = 0;
while(i < s[x].size())
{
if(s[x][i] == s[y][j])
{
i++;
j++;
if(j == s[y].size())
{
j = lps[j - 1];
}
}
else
{
if(j == 0)
{
i++;
}
else
{
j = lps[j - 1];
}
}
}
return j;
}
signed main()
{
in>>n;
for(int i = 0; i<n; i++)
{
in>>s[i];
}
for(int i = 0; i<n; i++)
{
for(int j = 0; j<n; j++)
{
if(i == j)
{
continue;
}
if(contains_secv(i, j) == 1)
{
useless[j] = 1;
}
}
}
for(int i = 0; i<n; i++)
{
if(useless[i] == 0)
{
continue;
}
swap(useless[i], useless[n - 1]);
swap(s[i], s[n - 1]);
n--;
i--;
}
for(int i = 0; i<n; i++)
{
for(int j = 0; j<n; j++)
{
if(i == j)
{
continue;
}
cost[i][j] = (int)s[j].size() - same_pref_suf(i, j);
// cout<<i<<" "<<j<<" "<<same_pref_suf(i, j)<<'\n';
}
}
for(int i = 0; i<n; i++)
{
for(int mask = 0; mask < (1 << n); mask++)
{
dp[i][mask] = INF;
}
}
for(int i = 0; i<n; i++)
{
dp[i][(1 << i)] = s[i].size();
last[i][(1 << i)] = -1;
}
for(int mask = 1; mask < (1 << n); mask++)
{
for(int i = 0; i<n; i++)
{
if(!(mask & (1 << i)))
{
continue;
}
for(int j = 0; j<n; j++)
{
if((mask & (1 << j)))
{
continue;
}
if(dp[i][mask] + cost[i][j] < dp[j][mask | (1 << j)])
{
dp[j][mask | (1 << j)] = dp[i][mask] + cost[i][j];
last[j][mask | (1 << j)] = i;
}
}
}
}
int cur = 0;
int mask = (1 << n) - 1;
for(int i = 0; i<n; i++)
{
if(dp[i][(1 << n) - 1] < dp[cur][(1 << n) - 1])
{
cur = i;
}
}
int lmin = dp[cur][(1 << n) - 1];
int poz = lmin - 1;
ans.resize(lmin);
while(cur != -1)
{
int nxt = last[cur][mask];
if(nxt == -1)
{
for(int i = 0; i<s[cur].size(); i++)
{
ans[i] = s[cur][i];
}
break;
}
int nr_char = cost[nxt][cur];
int ind = (int)s[cur].size() - nr_char;
for(int i = poz - nr_char + 1; i<=poz; i++)
{
ans[i] = s[cur][ind];
ind++;
}
poz -= nr_char;
mask ^= (1 << cur);
cur = nxt;
}
out<<ans;
return 0;
}