Cod sursa(job #195530)

Utilizator webspiderDumitru Bogdan webspider Data 19 iunie 2008 15:22:35
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.28 kb
#include <stdio.h>
#include <iostream>
#include <vector>

using namespace std;

const int maxN = 21;
const int maxC = 32002;
const int maxCD = (1<<18) * 18;
const int modH = 666013;
const int bzH = 19;

int N;
int coada[ maxCD ][ 2 ];
int dMin[ (1<<18) ][ 18 ];
int parent[ (1<<18) ][ 18 ];
char str[ maxN ][ maxC ];
int ln[ maxN ];

int solOrd[ maxN ];

int supp[ maxN ][ maxN ];
int lC;

long long hash1, hash2;

long long powF( int bz, int exp ) {
    long long rez = 1;
    long long aux = bz;
    for ( int i = 0; i < 16; i++ ) {
        if ( exp & ( 1 << i ) )
           rez = ( rez * aux ) % modH;
        aux = ( aux * aux ) % modH;
    }
    return rez;
}

bool eok( int X, int K ) {
    int R = 0;
    for ( int i = 0; i < maxN; i++ )
        if (  (1<<i) & K ) R++;
    return ( R == X );
}

int main()
{
#ifndef PC_COMPILE
    freopen("adn.in","r",stdin);
    freopen("adn.out","w",stdout);
#endif
#ifdef PC_COMPILE
	freopen("data.in","r",stdin);
	freopen("data.out","w",stdout);
#endif

	scanf("%d\n", &N );

	for ( int i = 0; i < N; i++ ) {
		scanf("%s\n", str[ i ] );
		ln[i] = strlen( str[i] );
	}
    int M =0;
    for ( int i = 0; i < N; i++ ) {
        hash1 = 0;
        for ( int j = 0; j < ln[i]; j++ )
            hash1 = ( hash1 + str[i][j]*powF( bzH, ln[i]-(j+1) ) ) % modH;
        int ins = 1;
        for ( int j = 0 && ins; j < N; j++ )
            if ( ln[i] <= ln[j] && i != j) {
                hash2 = 0;
                for ( int k = 0; k < ln[i]; k++ )
                    hash2 = ( hash2 + str[j][k]*powF( bzH, ln[i]-(k+1) ) ) % modH;
                if ( hash1 == hash2 ) {
                    ins =0;
                    break;
                }
                for ( int k = ln[i]; k < ln[j]; k++ ) {
                    hash2 = ( hash2 + 100*modH - str[j][k-ln[i]]*powF( bzH, ln[i]-1 ) ) % modH;
                    hash2 = ( hash2 * bzH + str[j][k] ) % modH;
                    if ( hash2 == hash1 ) {
                        ins = 0;
                        break;
                    }

                }
            }
        if ( ins ) {
            solOrd[M] = i;
            M++;
        }
    }
    N = M;
    for ( int i = 0; i < N; i++ ) {
		ln[ i ] = ln[ solOrd[i] ];
		memcpy( str[i], str[ solOrd[i] ], sizeof( str[i] ) );
    }
	for ( int i = 0; i < N; i++ )
		for ( int j = 0; j < N; j++ ) {
            hash1 = 0, hash2 = 0;

            for ( int l = 1; l <= min( ln[i], ln[j] ); l++ ) {
                hash1 = ( hash1 + str[i][ ln[i] - l ]*powF( bzH, l-1 ) ) % modH;
                hash2 = ( hash2*bzH + str[j][ l-1 ] ) % modH;

                if ( hash1 == hash2 )
                    supp[i][j] = l;
            }
	}
	coada[lC][0] = 0;
	coada[lC][1] = N;
	dMin[0][N] = 1;
	lC++;
	int sol = -1;

	for ( int i = 0; i < lC; i++ ) {
	    //printf("[%d] %d | %d   (%d){%d}\n", i, coada[i][0], coada[i][1], dMin[coada[i][0]][coada[i][1]], parent[coada[i][0]][coada[i][1]] );
	    if ( coada[i][0] == ( 1<<N )-1 ) {
	        if ( dMin[coada[i][0]][coada[i][1]] < dMin[coada[sol][0]][coada[sol][1]] || sol == -1) sol = i;
	    }

	    for ( int j = 0; j < N; j++ )
            if ( ! ( coada[i][0] & (1<<j) ) ) {
                if ( !dMin[ coada[i][0] + (1<<j) ][ j ] ) {
                    coada[lC][0] = coada[i][0] + (1<<j);
                    coada[lC][1] = j;
                    dMin[ coada[lC][0] ][ coada[lC][1] ] = dMin[coada[i][0]][coada[i][1]] + ln[j] - supp[coada[i][1]][j];
                    parent[ coada[lC][0] ][ coada[lC][1] ] = i;
                    lC++;
                }
                if ( dMin[ coada[i][0] + (1<<j) ][ j ] > dMin[ coada[i][0] ][ coada[i][1] ] + ln[j] - supp[ coada[i][1] ][ j ] ) {
                    dMin[coada[i][0]+(1<<j)][j] = dMin[coada[i][0]][coada[i][1]] +ln[j] - supp[coada[i][1]][j];
                    parent[ coada[i][0]+(1<<j) ][ j ] = i;
                }
            }
	}
	int i = N-1;
	while ( i >= 0 ) {
	    solOrd[i] = coada[ sol ][ 1 ];
	    sol = parent[ coada[sol][0] ][ coada[sol][1] ];
	    i--;
	}
    for ( int i = 0; i < N; i++ ) {
	    for ( int j = 0; j < ln[ solOrd[i] ] - supp[ solOrd[i] ][ solOrd[i+1] ]; j++ )
            printf("%c", str[ solOrd[i] ][ j ] );
	}
	printf("\n");
    return 0;
}