Cod sursa(job #2765267)

Utilizator DordeDorde Matei Dorde Data 26 iulie 2021 02:05:15
Problema ADN Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.75 kb
#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;
}
void Sift (){
    for(int i = 0 ; i < n ; ++ i)
        for(int j = 0 ; j < n ; ++ j)
            if (i != j && Match (i , j))
                viz [i] = 1;
    string s [M];
    pair <int , int> hl [M][Lg] , hr [M][Lg];
    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]);
        }
    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;
        }
    sol.push_back (ind);
    int cfg = (1 << n) - 1;
    for(int i = 1 ; i < n ; ++ i){
        ind = t [cfg][ind].first;
        sol.push_back (ind);
        cfg ^= (1 << ind);
    }
    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 [i].size () ; ++ j)
            ans += S [i][j];
    return ans;
}
int main (){
    Read ();
    Hash ();
    Sift ();
    BuildGraph ();
    Hamilton ();
    g << Solve ();
    return 0;
}