Pagini recente » Cod sursa (job #930244) | Cod sursa (job #286370) | Cod sursa (job #1901085) | Cod sursa (job #799080) | Cod sursa (job #2765268)
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
ifstream f ("adn.in");
ofstream g ("adn.out");
int const N = (1 << 19) , M = 19 , Lg = 30010 , m1 = 666013 , m2 = 1e9 + 7 , inf = (1 << 30);
int n , viz [M] , dp [N][M] , C [M][M];
pair <int , int> t [N][M] , hL [M][Lg] , hR [M][Lg] , aux [M][Lg];
string S [M];
vector <int> v [M];
int value (char x){
if (x == 'A')
return 1;
if (x == 'C')
return 2;
if (x == 'G')
return 3;
return 4;
}
void Read (){
f >> n;
for(int i = 0 ; i < n ; ++ i)
f >> S [i];
return;
}
void Hash (){
for(int i = 0 ; i < n ; ++ i){
hL [i][0] = mp (value (S [i][0]) , value (S [i][0]));
for(int j = 1 ; j < (int)S [i].size () ; ++ j){
int v1 = (5LL * hL [i][j - 1].first + value (S [i][j])) % m1;
int v2 = (5LL * hL [i][j - 1].second + value (S [i][j])) % m2;
hL [i][j] = mp (v1 , v2);
}
int sz = S [i].size () - 1 , p1 = 5 , p2 = 5;
hR [i][sz] = mp (value (S [i][sz]) , value (S [i][sz]));
for(int j = sz - 1 ; j >= 0 ; -- j){
int v1 = (1LL * p1 * value (S [i][j]) + hR [i][j + 1].first) % m1;
int v2 = (1LL * p2 * value (S [i][j]) + hR [i][j + 1].second) % m2;
hR [i][j] = mp (v1 , v2);
p1 = (5LL * p1) % m1;
p2 = (5LL * p2) % m2;
}
}
}
int Match (int i , int j){
if (S [i].size () > S [j].size ())
return 0;
int sz = S [i].size () ;
pair <int , int> val = hL [i][sz - 1];
pair <int , int> val2 = hL [j][sz - 1];
if (val == val2)
return 1;
int p1 = 1 , p2 = 1;
for(int k = 1 ; k < sz ; ++ k){
p1 = (5LL * p1) % m1;
p2 = (5LL * p2) % m2;
}
for(int k = sz ; k < (int)S [j].size () ; ++ k){
int v1 = val2.first , v2 = val2.second;
v1 = (5LL * v1 + value (S [j][k]) + 1LL * p1 * m1 - 5LL * p1 * value(S [j][k - sz])) % m1;
v2 = (5LL * v2 + value (S [j][k]) + 1LL * p2 * m2 - 5LL * p2 * value(S [j][k - sz])) % m2;
val2 = mp (v1 , v2);
if (val2 == val)
return 1;
}
return 0;
}
string s [M];
pair <int , int> hl [M][Lg] , hr [M][Lg];
void Sift (){
int b = 0;
for(int i = 0 ; i < n ; ++ i)
for(int j = 0 ; j < n ; ++ j)
if (i != j && Match (i , j))
viz [i] = 1;
int k = -1;
for(int i = 0 ; i < n ; ++ i)
if (! viz [i]){
s [++ k] = S [i];
copy (hL [i] , hL [i] + s [k].size () , hl [k]);
copy (hR [i] , hR [i] + s [k].size () , hr [k]);
}
++ k;
copy (s , s + k , S);
for(int i = 0 ; i < k ; ++ i){
copy (hl [i] , hl [i] + S [i].size () , hL [i]);
copy (hr [i] , hr [i] + S [i].size () , hR [i]);
}
n = k;
return;
}
int getEdge (int x , int y){
int r = 0;
for(int i = 0 ; i < min ((int)S [x].size () , (int)S [y].size ()) ; ++ i)
if (hR [x][S [x].size () - 1 - i] == hL [y][i])
r = i + 1;
return r;
}
void BuildGraph (){
for(int i = 0 ; i < n ; ++ i)
for(int j = 0 ; j < n ; ++ j)
if (i != j){
C [i][j] = getEdge (i , j);
v [j].push_back (i);
}
}
void Hamilton (){
for(int i = 0 ; i < (1 << n) ; ++ i)
for(int j = 0 ; j < n ; ++ j)
dp [i][j] = -inf;
for(int i = 0 ; i < n ; ++ i)
dp [(1 << i)][i] = 0;
for(int i = 1 ; i < (1 << n) ; ++ i)
for(int j = 0 ; j < n ; ++ j)
if (i & (1 << j))
for(int k = 0 ; k < (int)v [j].size () ; ++ k)
if (i & (1 << v [j][k]))
if (dp [i][j] < dp [i ^ (1 << j)][v [j][k]] + C [v [j][k]][j]){
dp [i][j] = dp [i ^ (1 << j)][v [j][k]] + C [v [j][k]][j];
t [i][j] = mp (v [j][k] , j);
}
return;
}
string Solve (){
string ans;
vector <int> sol;
int ind = 0 , mx = -inf;
for(int i = 0 ; i < n ; ++ i)
if (dp [(1 << n) - 1][i] > mx ){
mx = dp [(1 << n) - 1][i];
ind = i;
}
pair <int , int> curr = t [(1 << n) - 1][ind];
int cfg = (1 << n) - 1;
sol.push_back (curr.second);
sol.push_back (curr.first);
cfg ^= (1 << ind);
for(int i = 2 ; i < n ; ++ i){
curr = t [cfg][curr.first];
sol.push_back (curr.first);
cfg ^= (1 << curr.second);
}
reverse (sol.begin () , sol.end ());
ans += S [sol [0]];
for(int i = 1 ; i < (int)sol.size () ; ++ i)
for(int j = C [sol [i - 1]][sol [i]] ; j < (int)S [sol [i]].size () ; ++ j)
ans += S [sol [i]][j];
return ans;
}
int main (){
Read ();
Hash ();
Sift ();
BuildGraph ();
Hamilton ();
g << Solve ();
return 0;
}