Cod sursa(job #1935875)

Utilizator borcanirobertBorcani Robert borcanirobert Data 22 martie 2017 18:37:38
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.87 kb
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
using namespace std;

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

const int MAX = 18;
const int MAXL = 50005;
const int Inf = 0x3f3f3f3f;
int N;
vector<string> s;
int D[1<<MAX][MAX];
int b[MAX][MAX];
int p[MAX][MAXL];

void Read();
void Solve();
void BuildPrefix( int x );
void KMP( int x, int y );
void Write( int conf, int ul, int up );

int main()
{
    Read();
    Solve();

    fin.close();
    fout.close();
    return 0;
}

void Read()
{
    fin >> N; fin.get();
    s = vector<string>(N);
    for ( int i = 0; i < N; ++i )
    {
        fin >> s[i];
        BuildPrefix(i);
    }

   /* for ( int i = 0; i < N; ++i )
        fout << s[i] << '\n';   */
}

void Solve()
{
    int i, j, k;

    for ( i = 0; i < N; ++i )
        for ( j = 0; j < N; ++j )
            if ( i != j )
            {
                KMP(i, j);
            }

    int res{Inf}, u;
    for ( i = 0; i < N; ++i )
        D[1 << i][i] = s[i].size();
    for ( i = 0; i < ( 1 << N ); ++i )
    {
        int c{0};
        for ( j = 0; j < N; ++j )
            if ( i & ( 1 << j ) )
                ++c;
        if ( c < 2 )
            continue;

        for ( j = 0; j < N; ++j )
            if ( i & ( 1 << j ) )
            {
                D[i][j] = Inf;
                for ( k = 0; k < N; ++k )
                    if ( k != j && i & ( 1 << k ) )
                    {
                        D[i][j] = min( D[i][j], D[i ^ ( 1 << j )][k] + (int)s[j].size() - b[k][j] );
                    }
             //   fout << i << ' ' << j << ' ' << D[i][j] << '\n';

                if ( i + 1 == ( 1 << N ) && D[i][j] < res )
                    res = D[i][j], u = j;
            }
    }

    Write((1 << N) - 1, u, 0);
}

void Write( int conf, int ul, int up )
{
    for ( int i = 0; i < N; ++i )
        if ( i != ul && ( ( 1 << i ) & conf ) && D[conf][ul] == D[conf ^ ( 1 << ul )][i] + (int)s[ul].size() - b[i][ul] )
        {
            Write(conf ^ ( 1 << ul ), i, b[i][ul]);
            break;
        }

    for ( int i = 0; i < s[ul].size() - up; ++i )
        fout << s[ul][i];
}

void BuildPrefix( int x )
{
    int k{0};
    for ( int i = 1; i < s[x].size(); ++i )
    {
        while ( k > 0 && s[x][i] != s[x][k] )
            k = p[x][k - 1];
        if ( s[x][i] == s[x][k] )
            ++k;
        p[x][i] = k;
    }
}

void KMP( int x, int y )
{
    int k{0};
    for ( int i = 0; i < s[x].size(); ++i )
    {
        while ( k > 0 && s[x][i] != s[y][k] )
            k = p[y][k - 1];
        if ( s[x][i] == s[y][k] )
            ++k;
        if ( k == s[y].size() - 1 )
        {
            b[x][y] = s[y].size();
            return;
        }
    }

    b[x][y] = k;
  //  fout << x << ' ' << y << ' ' << k << '\n';
}