Pagini recente » Cod sursa (job #3279767) | Cod sursa (job #3244602) | Cod sursa (job #13148) | Cod sursa (job #3145591) | Cod sursa (job #3132292)
#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, indexes;
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)
{
for(int i = 0; i < limit; i ++)
cout << secvente[x][i];
}
void rebuildPath(int last)
{
int mask = (1 << (indexes.size())) - 1;
while(mask)
{
sol.pb(last);
int copyLast = last;
last = ult[mask][last];
mask -= (1 << copyLast);
}
for(int i = sol.size() - 1; i > 0; i --)
display(indexes[sol[i]], poz[indexes[sol[i]]][indexes[sol[i - 1]]]);
display(indexes[sol[0]], secvente[indexes[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;
}
if(isIndependent)
indexes.pb(i);
}
if(isLastIndependent)
indexes.pb(n - 1);
int noMasks = (1 << (indexes.size())) - 1;
for(int mask = 0; mask <= noMasks; mask ++)
for(int i = 0; i < indexes.size(); i ++)
dp[mask][i] = inf;
for(int i = 0; i < indexes.size(); i ++)
dp[1 << i][i] = secvente[indexes[i]].size();
for(int mask = 1; mask < noMasks; mask ++)
{
for(int i = 0; i < indexes.size(); i ++)
{
if(mask & (1 << i))
for(int poz = 0; poz < indexes.size(); poz ++)
if((mask & (1 << poz)) && dp[mask - (1 << poz)][i] != inf)
{
if(dp[mask][poz] > dp[mask - (1 << poz)][i] + c[indexes[i]][indexes[poz]])
{
dp[mask][poz] = dp[mask - (1 << poz)][i] + c[indexes[i]][indexes[poz]];
ult[mask][poz] = i;
}
}
}
}
int mask = noMasks, lastNode = -1;
for(int i = 0; i < indexes.size(); i ++)
{
if(mask & (1 << i))
for(int poz = 0; poz < indexes.size(); poz ++)
if((mask & (1 << poz)) && dp[mask - (1 << poz)][i] != inf)
{
if(dp[mask][poz] > dp[mask - (1 << poz)][i] + c[indexes[i]][indexes[poz]])
{
dp[mask][poz] = dp[mask - (1 << poz)][i] + c[indexes[i]][indexes[poz]];
ult[mask][poz] = i;
if(dp[mask][poz] < minCost)
{
minCost = dp[mask][poz];
lastNode = poz;
}
}
}
}
rebuildPath(lastNode);
return 0;
}
/*
AGATAGATGATAACCGCGCAGT 22
GATAACCGCGCAGTGATGAGA 21
TGATGAGATGGGGATATAAAA 21
ATGGGGATATAAAAACTTTTTT 22
GGATATAAAAAC 12
*/