Cod sursa(job #686126)

Utilizator psycho21rAbabab psycho21r Data 21 februarie 2012 14:04:00
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.06 kb
#include <fstream>
#include <vector>
#include <string>
#define INF 30001
#define FW(i,j) adn[i].size() <= adn[j].size() ? 0 : adn[i].size() - adn[j].size()
using namespace std;
bool out[18];
string adn[18];
vector<int> patterns[18];
void find_pat(int i)
{
    patterns[i].push_back(-1);
    patterns[i].push_back(0);
    int pos = 2, back = 0;

    while (pos < adn[i].size())
    {
        if(adn[i][pos-1] == adn[i][back])
        {
            ++back;
            patterns[i].push_back(back);
            ++pos;
        }
        else
        if(back > 0)
            back = patterns[i][back];
        else
        {
            patterns[i].push_back(0);
            ++pos;
        }
    }
}

bool search(int i, int j)
{
    int now = 0, x = 0;
    while (now + x < adn[j].size())
    {
        if(adn[i][x] == adn[j][now+x])
        {
            if(x == adn[i].size() - 1)
                return true;
            else
                ++x;
        }
        else
        {
            now = now + x - patterns[i][x];
            if(patterns[i][x] > -1)
                x = patterns[i][x];
            else
                x = 0;
        }
    }
    return false;
}

int supre(int i, int j)
{
    for(int w = FW(i,j); w < adn[i].size(); ++w)
    {
        int now = 0, x = w;
        while(adn[i][x] == adn[j][now])
        {
            if(x == adn[i].size() - 1)
                return adn[i].size()-w;
            ++x; ++now;
        }
    }
    return 0;
}

int main()
{
    int n, graph[18][18];
    ifstream in("adn.in");
    in >> n;
    for(int i = 0; i < n; ++i)
    {
        in >> adn[i];
        find_pat(i);
    }
    for(int i = 0; i < n; ++i)
        for(int j = 0; j < n; ++j)
        {
            if(adn[i].size()<adn[j].size())
                if(search(i,j))
                    out[i] = true;
            if(adn[i].size()==adn[j].size()&&adn[i]==adn[j]&&i!=j&&out[j]!=true)
                out[i] = true;
        }
    int N=0, map[18];
    for(int i = 0, j = 0; j < n; ++i, ++j)
    {
        j += out[j];
        map[i] = j;
        ++N;
    }
    vector<int> a[18];
    /*----Graph Contruction------------*/
    for(int i = 0; i < N; ++i)
    {
        for(int j = 0; j < N; ++j)
        {
            if(i!=j)
                graph[i][j] = supre(map[i],map[j]);
            else
                graph[i][j] = -1;
            a[j].push_back(i);
        }
    }
    int C[350][18];
    for(int i = 0; i < (1<<N); ++i)
        for(int j = 0; j < N; ++j)
            C[i][j] = -1;
    for(int i = 0; i < N; ++i)
    {
        C[1<<i][i] = 0;
    }
    int prev[18];
    for(int i = 1; i < (1<<N); ++i)
    {
        for(int j = 0; j < N; ++j)
        {
            if(i & (1<<j))
                for(int k = 0; k < a[j].size(); ++k)
                    if(i & (1<<a[j][k]))
                    {
                        if(C[i^(1<<j)][a[j][k]]!=-1&&C[i^(1<<j)][a[j][k]]+graph[a[j][k]][j]>C[i][j])
                        {
                            C[i][j] = C[i^(1<<j)][a[j][k]] + graph[a[j][k]][j];
                            prev[j] = a[j][k];
                        }
                    }
        }
    }
    int res = -1, end;
    for(int i = 0, w = 0; i < a[0].size(); ++i)
    {
        if(C[(1<<N)-1][a[0][i]]+graph[a[0][i]][0] > res)
        {
            res = C[(1<<N)-1][a[0][i]]+graph[a[0][i]][0];
            end = i;
        }
    }
    int min = graph[2][0], start = 0;
    for(int i = 1; i < N; ++i)
    {
        if(graph[prev[i]][i]<min)
        {
            min = graph[prev[i]][i];
            start = i;
        }
    }
    vector<int> fin;
    for(int i = prev[start], k = 1; i != prev[start] || k; i = prev[i], k = 0)
    {
        fin.push_back(i);
    }
    ofstream out("adn.out");
    out << adn[map[fin[fin.size()-1]]];
    for(int i = fin.size()-2; i>=0; --i)
    {
        for(int j = graph[fin[i+1]][fin[i]]; j < adn[map[fin[i]]].size(); ++j)
            out << adn[map[fin[i]]][j];
    }
    out.close();
    return 0;
}