Cod sursa(job #1490964)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 24 septembrie 2015 15:44:18
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.5 kb
#include<fstream>
#include<string>
#include<cstring>

using namespace std;

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

const int lgmax = 30001;
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 ];

string s[ nmax + 1 ];

inline int adauga( int i, int x, int j ) {
    return (d[ i - (1 << (j - 1)) ][ 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 ;
        }
    }
    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 ;
    }
    reconst( st - (1 << (last - 1)), r[ st ][ last ] );

    for( int i = c[ ( int )r[ st ][ last ] ][ last ] + 1; i < ( int )s[ last ].size(); ++ i ) {
        fout << s[ last ][ i ];
    }
}
int main() {
    fin >> n;
    for( int i = 1; i <= n; ++ i ) {
        fin >> s[ i ];
        s[ i ] = "#" + s[ i ];
    }

    precalc();

    d[ 0 ][ 0 ] = 0;
    for( int i = 1; i < (1 << n); ++ i ) {
        for( int j = 1; j <= n; ++ j ) {
            d[ i ][ j ] = inf;
            if ( i & (1 << (j - 1)) ) {
                if ( i == (1 << (j - 1)) ) {
                    d[ i ][ j ] = ( int )s[ j ].size() - 1;
                }
                bool ok = 0;
                for( int x = 1; x <= n; ++ x ) {
                    if ( i & (1 << (x - 1)) && x != j ) {
                        if ( c[ x ][ j ] == ( int )s[ j ].size() - 1 ) {
                            ok = 1;
                        }
                        if ( d[ i ][ j ] > adauga( i, x, j ) ) {
                            r[ i ][ j ] = x;
                            d[ i ][ j ] = adauga( i, x, j );
                            p[ i ][ j ] = ( int )s[ j ].size() - c[ x ][ j ];
                        }
                    }
                }
                if ( ok == 1 ) {
                    d[ i ][ j ] = inf;
                    for( int x = 1; x <= n; ++ x ) {
                        if ( i & (1 << (x - 1)) && x != j ) {
                            if ( d[ i ][ j ] > d[ i - (1 << (j - 1)) ][ x ] ) {
                                d[ i ][ j ] = d[ i - (1 << (j - 1)) ][ x ];
                                r[ i ][ j ] = x;
                                p[ i ][ j ] = ( int )s[ j ].size();
                            }
                        }
                    }
                }
            }
        }
    }

    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 );

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