Cod sursa(job #1979303)

Utilizator raulmuresanRaul Muresan raulmuresan Data 10 mai 2017 10:05:58
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.73 kb
#include<fstream>
#include<vector>
#include<string>
#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[30100];
int w[NMAX], lung[NMAX];

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

void init()
{
    for(i = 0; i < 1 << n; i++)
    {
        for(j = 0; j <= NMAX; j++)
        {
            d[i][j] = 1000000000;
        }
    }
}

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

    k = 0;
    for(int i = 1; i < a.size(); i++)
    {
        //fout << a[i];
        while(k > 0 && b[k + 1] != a[i])
        {
            k = prefix[k];
        }
        if(b[k + 1] == a[i])
        {
            k++;
        }
        if(k == b.size() - 1)
        {
            //fout << "intra\n";
            included[y] = 1;
            //sol.push_back(i - n);
            k = prefix[k];
        }
    }
    //fout <<"\n";
    //fout << k <<"\n";
    //fout << a <<" "<<b << " " << k <<"\n";
    aux[x][y] = k;
    //fout << k <<"\n"


   /* fout << b <<"\n";
    for(i = 1; i < b.size(); i++)
    {
        fout << prefix[i] << " ";
    }
    fout <<"\n";*/
    //fout <<"\n";

}



int main()
{
    fin >> n;
    init();
    for(i = 0; i < n; i++)
    {
        fin >> word[i];
        lung[i] = word[i].size();
        word[i] = ' ' + word[i];
        //fout << word[i] << "\n";
    }
    //sort(word + 1, word + n + 1, cmp);
    init();
    /*for(i = 1; i <= n; i++)
    {
        for(j = 1; j <= n; j++)
        {
            if(i != j)
            {
                fout << word[i] << " " << word[j] <<"\n";
            }
        }
    }*/

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

            //fout <<i  <<" "<<j <"\n";
            if(i != j)
            {
                getPrefix(word[i], word[j], i, j);
                //fout << i <<" "<<j <<" " <<aux[i][j]<<"\n";

            }


        }
    }
    int newN = 0;
    for(i = 0;i < n; i++)
    {
        //fout << included[i] << " ";
        if(included[i] == 0)
        {
            //fout << word[i] <<"\n";
            //words[newN] = word[i];
            w[newN] = i;
            newN++;
        }
    }
    //fout << newN <<"\n";
    n = newN;
    //fout << newN<<"\n";
    for(i = 0; i < n; i++)
    {
        //fout << word[w[i]] << "\n";
    }
    /*for(int i = 0; i < n; i++)
    {
        //fout << word[i] << "\n";
        for(int j = 0; j < n; j++)
        {
            ///cel mai lung sufix al lui i care este prefix al lui j
            //aux[i][j] = getPrefix(word[i], word[j]);

            //fout <<i  <<" "<<j <"\n";
            if(i != j)
            {
                getPrefix(words[i], words[j], i, j);
                //fout << i <<" "<<j <<" " <<aux[i][j]<<"\n";

            }


        }
    }*/



    for(i = 0; i < n;i++)
    {
        //fout << word[i].size() - 1 <<"\n";
        d[(1 << i)][i] = lung[w[i]];
        last[(1 << i)][i] = -1;
    }


    for(int stare = 1; stare < 1 << n; stare++)
    //for(int stare = 1; stare < 2; stare++)
    {
        for(i = 0; i < n; i++)
        {
            if(d[stare][i] != INF)
            {
                //fout << stare<<" "<<i<<"\n";
                for(j = 0; j <n; j++)
                {
                    if(i != j && ((stare & (1 << j) )== 0))
                    {
                        //fout <<
                        int lPrefix = aux[w[i]][w[j]];
                        int value = lung[w[j]] - aux[w[i]][w[j]];
                        if(d[(stare + (1 << j))][j] > d[stare][i] + value)
                        {
                            d[(stare + (1 << j))][j] = d[stare][i] + value;
                           // fout <<"noua dinamica " << (stare + (1 << j)) <<" " << d[stare][i] + value <<"\n";
                            last[(stare + (1 << j))][j] = i;
                        }

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

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

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

    //fout <<d[30][4]<<"\n";



}