Cod sursa(job #2341590)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 11 februarie 2019 23:04:50
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.08 kb
#include <bits/stdc++.h>

#define MAXN        20
#define MAXLEN   35005
#define INF 1000000005

int N, K, V[MAXN][MAXN], Len[MAXN],
    DP[1<<18][MAXN];
char Seq[MAXN][MAXLEN];

int LPS[MAXLEN];
void DoLPS(char S[], int N) {
	int len = 0;
	LPS[0] = 0;
	for (int i=1; i<=N; ++i) {
        while (len && S[len] != S[i])
            len = LPS[len-1];
        if (S[len] == S[i])
            ++len;
        LPS[i] = len;
	}
}

int KMP(char S[], char T[], int N, int M) {
    DoLPS(S, N);
    int len = 0;
    for (int i=0; i<=M; ++i) {
        while (len && S[len] != T[i])
            len = LPS[len-1];
        if (S[len] == T[i])
            ++len;
        if (len == N+1) return INF;
    }   return len;
}

std::ifstream In ("adn.in");
std::ofstream Out("adn.out");

void Print(int Bits, int Index) {
    if (Bits == (1<<(Index-1))) {
        Out << Seq[Index];
        return;
    }
    for (int i=1; i<=N; ++i)
        if (DP[Bits][Index] == DP[Bits ^ (1<<(Index-1))][i] - V[i][Index]) {
            Print(Bits ^ (1<<(Index-1)), i);
            Out << Seq[Index] + V[i][Index];
            i = N+5;
        }
}

void Citire() {
    In >> N;
    for (int i=1; i<=N; ++i)
        In >> Seq[i], Len[i] = strlen(Seq[i])-1;
}

void Rezolvare() {
    K = (1<<N) - 1;
    memset(DP, 100, sizeof(DP));
    DP[0][0] = 0;

	for (int i=1, j; i<=N; ++i)
        for (j=1; j<=N; ++j)
            if (i != j && (K&(1<<(j-1)))) {
                V[i][j] = KMP(Seq[j], Seq[i], Len[j], Len[i]);
                if (V[i][j] == INF)
                    K ^= (1<<(j-1));
            }

	for (int i=1, j, k; i<=K; ++i)
        for (j=1; j<=N; ++j) {
            if (!(1<<(j-1))&K && !(1<<(j-1))&i) continue;
            for (k=0; k<=N; ++k)
                if (k != j)
                    DP[i][j] = std::min(DP[i][j], DP[i^(1<<(j-1))][k] - V[k][j]);
        }

	int idx = 0;
	DP[K][0] = INF;
	for (int i=1; i<=N; ++i)
        if (DP[K][i] < DP[K][idx])
            idx = i;
    Print(K, idx);
}

int main()
{
    Citire();
    Rezolvare();

	return 0;
}