Pagini recente » Cod sursa (job #2875621) | Cod sursa (job #73346) | Cod sursa (job #3402) | Cod sursa (job #380184) | Cod sursa (job #3132283)
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define MAX_N 18
#define MAX_STATE 263000
const int inf = INT_MAX;
int n, minCost;
int c[MAX_N + 1][MAX_N + 1], poz[MAX_N + 1][MAX_N + 1];
int dp[MAX_STATE][19];
short ult[MAX_STATE][19];
vector <string> secvente;
vector <int> pi, sol, index;
int kmp(int x, int y)/// suprapune b + a
{
pi.clear();
int aSize = secvente[x].size();
int bSize = secvente[y].size();
string a = secvente[x] + '#' + secvente[y];
pi.resize(a.size() + 1);
int j;
bool ok = 1;
for(int i = 1; i < a.size() && ok; i ++)
{
j = pi[i - 1];
while(j && a[j] != a[i])
j = pi[j - 1];
if(a[j] == a[i])
j ++;
pi[i] = j;
if(pi[i] == aSize)
ok = 0;
}
if(ok)
{
poz[y][x] = bSize - pi[a.size() - 1];/// poz de la care incepe al doilea string cand le suprapui
return aSize - pi[a.size() - 1];
}
poz[y][x] = -1;
return 0;
}
void display(int x, int limit)
{
// if(limit == -1)
// limit = secvente[x]
for(int i = 0; i < limit; i ++)
cout << secvente[x][i];
// cout << limit << "\n";
// cout << secvente[y];
}
void rebuildPath(int last)
{
int mask = (1 << (index.size())) - 1;
// cout << "Cale\n";
while(mask)
{
sol.pb(last);
int copyLast = last;
// cout << last << " ";
// cout << mask << "\n";
last = ult[mask][last];
mask -= (1 << copyLast);
}
// cout << "\n";
for(int i = sol.size() - 1; i > 0; i --)
{
// cout << "\n" << index[sol[i]] << " " << index[sol[i - 1]] << "\n";
display(index[sol[i]], poz[index[sol[i]]][index[sol[i - 1]]]);
}
display(index[sol[0]], secvente[index[sol[0]]].size());
}
int main()
{
ios_base :: sync_with_stdio(0);
cin.tie(0);
freopen("adn.in", "r", stdin);
freopen("adn.out", "w", stdout);
cin >> n;
minCost = INT_MAX;
secvente.resize(n + 1);
for(int i = 0; i < n; i ++)
{
cin >> secvente[i];
}
bool isLastIndependent = 1;
for(int i = 0; i < n - 1; i ++)
{
bool isIndependent = 1;
for(int j = i + 1; j < n; j ++)
{
c[i][j] = kmp(j, i);
c[j][i] = kmp(i, j);
if(c[j][i] == 0)
isIndependent = 0;
if(j == n - 1 && c[i][j] == 0)
isLastIndependent = 0;
// cout << i << " " << j << " " << c[i][j] << " " << poz[i][j] << " " << c[j][i] << " " << poz[j][i] << "\n";
}
if(isIndependent)
{
index.pb(i);
}
// else cout << "ddds" << i;
}
// cout << "\n" << index.size() << "\n";
if(isLastIndependent)
{
index.pb(n - 1);
}
// cout << index.size();
int noMasks = (1 << (index.size())) - 1;
for(int mask = 0; mask <= noMasks; mask ++)
for(int i = 0; i < index.size(); i ++)
dp[mask][i] = inf;
for(int i = 0; i < index.size(); i ++)
dp[1 << i][i] = secvente[index[i]].size();
for(int mask = 1; mask < noMasks; mask ++)
{
for(int i = 0; i < index.size(); i ++)
{
if(mask & (1 << i))
for(int poz = 0; poz < index.size(); poz ++)
if((mask & (1 << poz)) && dp[mask - (1 << poz)][i] != inf)
{
if(dp[mask][poz] > dp[mask - (1 << poz)][i] + c[index[i]][index[poz]])
{
dp[mask][poz] = dp[mask - (1 << poz)][i] + c[index[i]][index[poz]];
ult[mask][poz] = i;
}
}
}
}
// for(int mask = 1; mask <= noMasks; mask ++) /// mask = 0 sau 1 ?? 1
// {
// cout << mask << ": ";
// for(int i = 0; i < n; i ++)
// {
// cout << dp[mask][i] << " ";
// }
// cout << "\n";
// }
int mask = noMasks, lastNode = -1;
// cout << "no a " << noMasks << "\n";
for(int i = 0; i < index.size(); i ++)
{
if(mask & (1 << i))
for(int poz = 0; poz < index.size(); poz ++)
if((mask & (1 << poz)) && dp[mask - (1 << poz)][i] != inf)
{
if(dp[mask][poz] > dp[mask - (1 << poz)][i] + c[index[i]][index[poz]])
{
dp[mask][poz] = dp[mask - (1 << poz)][i] + c[index[i]][index[poz]];
// cout << "am intrat" << mask << " " << poz << " " << dp[mask][poz] << "\n";
ult[mask][poz] = i;
if(dp[mask][poz] < minCost)
{
minCost = dp[mask][poz];
lastNode = poz;
}
}
}
}
rebuildPath(lastNode);
// cout << minCost;
return 0;
}