Cod sursa(job #1488651)

Utilizator iordache.bogdanIordache Ioan-Bogdan iordache.bogdan Data 19 septembrie 2015 14:01:56
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.7 kb
#include <fstream>
#include <cstring>
#include <algorithm>
#include <vector>

#define DIM 18
#define LEN 30005
#define infile "adn.in"
#define outfile "adn.out"

using namespace std;

ifstream fin(infile);
ofstream fout(outfile);

char seq[DIM + 1][LEN];

int pi[DIM + 1][LEN];

int cost[DIM + 1][DIM + 1];

int sol[DIM + 1], w[DIM + 1];

bool useless[DIM];

int dp[1 << DIM][DIM + 1], t[1 << DIM][DIM + 1];

int main() {

	int n;

	fin >> n;

	for (int i = 1; i <= n; ++i) {

		fin >> seq[i] + 1;

	}

	//prefix function

	for (int i = 1; i <= n; ++i) {

		int q;

		for (int j = 2; seq[i][j]; ++j) {

			q = pi[i][j - 1];

			while (q && seq[i][j] != seq[i][q + 1])
				q = pi[i][q];

			if (seq[i][j] == seq[i][q + 1])
				pi[i][j] = q + 1;

		}

	}

	//merge cost

	for (int i = 1; i <= n; ++i) {

		for (int j = 1; j <= n; ++j) {

			if (i == j)
				continue;

			cost[i][j] = -1;

			int q = 0;

			for (int pos = 1; seq[i][pos]; ++pos) {

				while (q && seq[i][pos] != seq[j][q + 1])
					q = pi[j][q];

				if (seq[i][pos] == seq[j][q + 1])
					++q;

				if (q == strlen(seq[j] + 1)) {

					cost[i][j] = 0;

					useless[j] = true;

					break;

				}

			}

			if (cost[i][j] == -1) {

				cost[i][j] = strlen(seq[j] + 1) - q;

			}

		}

	}

	int m = 0;

	for (int i = 1; i <= n; ++i)
		if (!useless[i])
			w[++m] = i;


	//dynamic programming

	for (int config = 1, i = 1; config < (1 << m); config <<= 1, ++i) {

		dp[config][i] = strlen(seq[w[i]] + 1);

		t[config][i] = -1;

	}


	for (int config = 1; config < (1 << m); ++config) {

		if (!(config & (config - 1)))
			continue;

		for (int i = 1; i <= m; ++i) {

			if (!(config & (1 << (i - 1))))
				continue;

			dp[config][i] = 2000000000;

			t[config][i] = -1;

			for (int j = 1; j <= m; ++j) {

				if (i == j || !(config & (1 << (j - 1))))
					continue;

				int aux = dp[config ^ (1 << (i - 1))][j] + cost[w[j]][w[i]];

				if (aux < dp[config][i]) {

					dp[config][i] = aux;

					t[config][i] = j;

				}

			}

		}

	}


	int last, minim = 2000000000;

	for (int i = 1; i <= m; ++i) {

		if (minim > dp[(1 << m) - 1][i]) {

			minim = dp[(1 << m) - 1][i];

			last = i;

		}

	}

	int nr = 0, conffig = ((1 << m) - 1);

	while (last != -1) {

		sol[++nr] = w[last];

		int temp = last;

		last = t[conffig][last];

		conffig ^= (1 << (temp - 1));

	}

	fout << seq[sol[nr]] + 1;

	for (int i = nr - 1; i; --i) {

		for (int j = strlen(seq[sol[i]] + 1) - cost[sol[i + 1]][sol[i]] + 1; seq[sol[i]][j]; ++j)
			fout << seq[sol[i]][j];

	}

	return 0;

}

//Trust me, I'm the Doctor!