Cod sursa(job #1652941)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 15 martie 2016 16:56:16
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.47 kb
#include<fstream>
#include<string>
#include<cstring>
#include<vector>

using namespace std;

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

const int lgmax = 30002;
const int inf = 1 << 30;
const int nmax = 18;
int n;
int pi[ lgmax + 1 ];
int c[ nmax + 1 ][ nmax + 1 ];
int d[ (1 << nmax) ][ nmax + 1 ], p[ (1 << nmax) + 1 ][ nmax + 1 ];
char r[ (1 << nmax) ][ nmax + 1 ];

vector< int > incl[ nmax + 1 ];

string s[ nmax + 1 ];

inline int adauga( int i, int x, int j ) {
    return ( d[ i ][ x ] + ( int )s[ j ].size() - 1 - c[ x ][ j ] );
}
void kmp( int x, int y ) {
    memset( pi, 0, sizeof( pi ) );
    pi[ 1 ] = 0;
    for( int i = 2; i < ( int )s[ x ].size(); ++ i ) {
        int r = pi[ i - 1 ];
        while ( r != 0 && s[ x ][ r + 1 ] != s[ x ][ i ] ) {
            r = pi[ r ];
        }

        if ( s[ x ][ r + 1 ] == s[ x ][ i ] ) {
            pi[ i ] = r + 1;
        } else {
            pi[ i ] = 0;
        }
    }

    int r = 0;
    for( int i = 1; i < ( int )s[ y ].size(); ++ i ) {
        while ( r != 0 && s[ x ][ r + 1 ] != s[ y ][ i ] ) {
            r = pi[ r ];
        }

        if ( s[ x ][ r + 1 ] == s[ y ][ i ] ) {
            ++ r;
        }
        if ( r == ( int )s[ x ].size() - 1 ) {
            c[ y ][ x ] = r; return ;
            incl[ y ].push_back( x );
        }
    }
    c[ y ][ x ] = r;
}
void precalc() {
    for( int i = 1; i <= n; ++ i ) {
        for( int j = 1; j <= n; ++ j ) {
            kmp( i, j );
        }
    }
}
void reconst( int st, int last ) {
    if ( st == 0 ) {
        return ;
    }

    int u = r[ st ][ last ];
    if ( c[ last ][ u ] == ( int )s[ u ].size() - 1 ) {
        reconst( st - (1 << (u - 1)), last );
    } else {
        reconst( st - (1 << (last - 1)), u );

        for( int i = p[ st ][ last ]; i < ( int )s[ last ].size(); ++ i ) {
            fout << s[ last ][ i ];
        }
    }
}
int main() {
    fin >> n;
    for( int i = 0; i < (1 << n); ++ i ) {
        for( int j = 1; j <= n; ++ j ) {
            d[ i ][ j ] = inf;
        }
    }
    for( int i = 1; i <= n; ++ i ) {
        fin >> s[ i ];
        s[ i ] = "#" + s[ i ];
        d[ (1 << (i - 1)) ][ i ] = ( int )s[ i ].size() - 1;
        p[ (1 << (i - 1)) ][ i ] = 1;
    }

    precalc();

    for( int i = 1; i < (1 << n); ++ i ) {
        for( int j = 1; j <= n; ++ j ) {
            if ( ( i & (1 << (j - 1)) ) == 0 ) {
                continue;
            }

            int mask = i - (1 << (j - 1));
            for( int x = 1; x <= n; ++ x ) {
                if ( ( mask & (1 << (x - 1)) ) ) {
                    if ( d[ i ][ j ] > adauga( mask, x, j ) ) {
                        d[ i ][ j ] = adauga( mask, x, j );
                        p[ i ][ j ] = c[ x ][ j ] + 1;
                        r[ i ][ j ] = x;
                    }
                }
            }

            for( vector< int >::iterator it = incl[ j ].begin(); it != incl[ j ].end(); ++ it ) {
                int shp = i | (1 << (*it - 1));
                if ( d[ shp ][ j ] > d[ i ][ j ] ) {
                    d[ shp ][ j ] = d[ i ][ j ];
                    p[ shp ][ j ] = ( int )s[ *it ].size();
                    r[ shp ][ j ] = *it;
                }
            }
        }
    }

    int last = 0;
    d[ (1 << n) - 1 ][ 0 ] = inf;
    for( int i = 1; i <= n; ++ i ) {
        if ( d[ (1 << n) - 1 ][ last ] > d[ (1 << n) - 1 ][ i ] ) {
            last = i;
        }
    }

    reconst( (1 << n) - 1, last );
    fout << "\n";

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