Cod sursa(job #2341429)

Utilizator toadehuPuscasu Razvan Stefan toadehu Data 11 februarie 2019 20:07:57
Problema ADN Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.54 kb
#include<fstream>
#include<vector>
#include<cstring>
#include<algorithm>

#define modulo 666013
#define INF 10000000

using namespace std;

ifstream fin("adn.in");
ofstream fout("adn.out");

const int NMAX = 19;

string sir;

int i, n, k, j,contor,st,dr,x,y;

string word[NMAX], words[NMAX];

int d[1 << NMAX][NMAX];

int last[1 << NMAX][NMAX];

int aux[NMAX][NMAX];

int included[30100];

int prefix[NMAX][30100];

int w[NMAX], lung[NMAX];


bool cmp(string a, string b)
{
    return a.size() < b.size();
}

void generatePrefix(string& b, int x)
{
    prefix[x][1] = 0;
    int k = 0;
    for(int i = 2; i < b.size(); i++)
    {
        while(k > 0 && b[k + 1] != b[i])
        {
            k = prefix[x][k];
        }
        if(b[k + 1] == b[i])
        {
            k++;
        }
        prefix[x][i] = k;
    }


}

int getPrefix(string& a, string &b,int x, int y)
{


    k = 0;
    for(int i = 1; i < a.size(); i++)
    {
        while(k > 0 && b[k + 1] != a[i])
        {
            k = prefix[y][k];
        }
        if(b[k + 1] == a[i])
        {
            k++;
        }
        if(k == b.size() - 1)
        {
            included[y] = 1;
            k = prefix[y][k];
        }
    }
    aux[x][y] = k;

}



int main()
{
    fin >> n;
    for(i = 0; i < n; i++)
    {
        fin >> word[i];
        lung[i] = word[i].size();
        word[i] = ' ' + word[i];
        generatePrefix(word[i], i);
    }

    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            ///cel mai lung sufix al lui i care este prefix al lui j
            if(i != j)
            {
                getPrefix(word[i], word[j], i, j);
            }


        }
    }
    int newN = 0;
    for(i = 0; i < n; i++)
    {
        if(included[i] == 0)
        {
            w[newN] = i;
            newN++;
        }
    }
    //fout << newN <<"\n";
    n = newN;

    for(i = 0; i < n; i++)
    {
        d[(1 << i)][i] = lung[w[i]];
        last[(1 << i)][i] = -1;
    }


    for(int stare = 1; stare < 1 << n; stare++)
    {
        for(i = 0; i < n; i++)
        {
            if(d[stare][i] != 0)
            {
                for(j = 0; j <n; j++)
                {
                    if(i != j && ((stare & (1 << j) )== 0))
                    {
                        int lPrefix = aux[w[i]][w[j]];
                        int value = lung[w[j]] - aux[w[i]][w[j]];
                        if(d[(stare + (1 << j))][j] == 0 || d[(stare + (1 << j))][j] > d[stare][i] + value)
                        {
                            d[(stare + (1 << j))][j] = d[stare][i] + value;
                            last[(stare + (1 << j))][j] = i;
                        }

                    }
                }
            }
        }
    }
    int minim = INF;
    int pos = -1;
    for(i = 0; i < n; i++)
    {
        if(minim > d[(1 << n) - 1][i])
        {
            minim = d[(1 << n) - 1][i];
            pos = i;
        }
    }
    int stare = (1 << n) - 1;
    string sol = "";
    while(last[stare][pos] != -1)
    {
        int newPos = last[stare][pos];
        int nr = aux[w[newPos]][w[pos]];
        string aux = "";
        for(i = nr+1; i <= lung[w[pos]]; i++)
        {
            aux = aux + word[w[pos]][i];
        }
        sol = aux + sol;

        stare = stare - (1 << pos);
        pos = newPos;
    }

    sol = word[w[pos]] + sol;
    sol.erase(0, 1);
    fout << sol << "\n";

}