Cod sursa(job #2591966)

Utilizator cyg_vladioanBirsan Vlad cyg_vladioan Data 31 martie 2020 19:09:02
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.95 kb
#include <cstdio>
#include <string>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int NMAX = 18;
const int LMAX = 30000;
const int INF = 2.e9;
struct muchii
{
    int nod , cost , poz;
};
muchii temp;
vector <muchii> G[NMAX + 5];
vector <string> v;
vector <int> ans;
string s;
int d[1 << 18][NMAX + 1] , pr[1 << 18][NMAX + 1] , urm[LMAX + 5] , fbd;
void prefix(string y)//y-pattern
{
    int m , i , k;
    urm[1] = 0;
    m = y.length() - 1;
    k = 0;
    for(i = 2 ; i <= m ; i ++)
    {
        while(k > 0 && y[k + 1] != y[i])
            k = urm[k];
        if(y[k + 1] == y[i])
            k ++;
        urm[i] = k;
    }
}
int KMP(int a , int b)
{
    string x , y;
    x = " " + v[a];
    y = " " + v[b];
    prefix(y);
    int n , m , i , k;
    n = x.length() - 1;
    m = y.length() - 1;
    k = 0;
    for(i = 1 ; i <= n ; i ++)
    {
        while(k > 0 && y[k + 1] != x[i])
            k = urm[k];
        if(y[k + 1] == x[i])
            k ++;
        if(k == m)
            return i - m;
        if(i == n)
        {
            if(k == 0)
                return -1;
            return i - k;
        }
    }
}
int unionstr(int x , int y)
{
    int poz = KMP(x , y);
    if(poz == -1)
    {
        temp.nod = y;
        temp.cost = v[y].size();
        temp.poz = 0;
        G[x].push_back(temp);
    }
    else if(poz + v[y].length() > v[x].length() && poz != 0)
    {
        temp.nod = y;
        temp.cost = poz + v[y].length() - v[x].length();
        temp.poz = v[x].length() - poz;
        G[x].push_back(temp);
    }
    else
    {
        if(poz == 0 && v[x].length() > v[y].length())
            fbd = (fbd | (1 << y));
        else if(poz == 0 && v[x].length() < v[y].length())
            fbd = (fbd | (1 << x));
        else if(poz == 0 && v[x].length() == v[y].length() && x < y)
            fbd = (fbd | (1 << x));
        else
            fbd = (fbd | (1 << y));
    }
}
void afisare(int x , int y)
{
    int i , j;
    for(i = 0 ; i < G[x].size() ; i ++)
        if(G[x][i].nod == y)
            break;
    for(j = G[x][i].poz ; j < v[y].length() ; j ++)
        printf("%c" , v[y][j]);
}
int main()
{
    freopen("adn.in" , "r" , stdin);
    freopen("adn.out" , "w" , stdout);
    int n , i , j , lim , k , bm , l , c , lmin , aux;
    scanf("%d\n" , &n);
    for(i = 1 ; i <= n ; i ++)
    {
        getline(cin , s);
        //s.insert(0 , ' ');
        v.push_back(s);
    }
    for(i = 0 ; i < n ; i ++)
        for(j = 0 ; j < n ; j ++)
            if(i != j)
                unionstr(i , j);
    lim = (1 << n) - 1;
    for(i = 0 ; i <= lim ; i ++)
        for(j = 0 ; j < n ; j ++)
            d[i][j] = INF;
    for(j = 0 ; j < n ; j ++)
        if((fbd & (1 << j)) == 0)
        {
            d[(1 << j)][j] = v[j].length();
            pr[(1 << j)][j] = -1;
        }
    for(i = 0 ; i <= lim ; i ++)
        for(j = 0 ; j < n ; j ++)
            if((i & (1 << j)) != 0)
                for(k = 0 ; k < G[j].size() ; k ++)
                    if((fbd & (1 << G[j][k].nod)) == 0)
                    {
                        bm = (i | (1 << G[j][k].nod));
                        if(d[bm][G[j][k].nod] > d[i][j] + G[j][k].cost)
                        {
                            d[bm][G[j][k].nod] = d[i][j] + G[j][k].cost;
                            pr[bm][G[j][k].nod] = j;
                        }
                    }
    l = (lim ^ fbd);
    lmin = INF;
    for(j = 0 ; j < n ; j ++)
        if(d[l][j] < lmin)
        {
            lmin = d[l][j];
            c = j;
        }
    ans.push_back(c);
    while(pr[l][c] != -1)
    {
        ans.push_back(pr[l][c]);
        aux = pr[l][c];
        l = (l ^ (1 << c));
        c = aux;
    }
    printf("%s" , v[ans[ans.size() - 1]].c_str());
    for(i = ans.size() - 1 ; i > 0 ; i --)
        afisare(ans[i] , ans[i - 1]);
    return 0;
}