Cod sursa(job #33777)

Utilizator IgnitionMihai Moraru Ignition Data 19 martie 2007 20:00:31
Problema ADN Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 2.9 kb
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MN (20)
#define ML (30009)
#define MCFG (262144)

char sraw[MN][ML];
int svalid[MN], sprefix[MN][ML], prefix[ML], slen[MN];
int graw[MN][MN], g[MN][MN], s[MN];
int N, newN;
int _c[MN][MCFG], _prev[MN][MCFG];
int cmax, start;

int c(int start, int cfg)
{
	if(_c[start][cfg] != -1)
		return _c[start][cfg];
        int i, tmp;
	for(i = 0; (1 << i) <= cfg; ++ i) if(cfg&(1 << i) && i-start) {
                tmp = c(i, cfg-(1 << start));
                tmp += g[start][i];
		if(tmp > _c[start][cfg]) {
			_c[start][cfg] = tmp;
			_prev[start][cfg] = i;
		}
        }
	return _c[start][cfg];
}

void gen_prefix(int *p, char *s)
{
	int i, k;
	memset(p, 0, sizeof(p));
	-- s;
	for(k = 0, i = 2; isalpha(s[i]); p[i ++] = k) {
		for(; k && s[k+1] != s[i]; k = p[k]);
		k += s[k+1] == s[i];
	}
}

void kmp(int *out, char *h, char *n, int *p) // h = haystack, n = needle, p[i] = prefix(n[i])
{
	int i, k;
	memset(out, 0, sizeof(out));
	-- h; -- n;
	for(k = 0, i = 1; isalpha(h[i]); out[i ++] = k) {
		for(; k && n[k+1] != h[i]; k = p[k]);
		k += n[k+1] == h[i];
	}
}

int main()
{
	int i, j, k;

	freopen("adn.in", "r", stdin);
	scanf("%d", &N);
	for(i = 0; i < N; ++ i)
		scanf("%s", sraw[i]);
	fclose(stdin);

	// Generate prefixes
	for(i = 0; i < N; ++ i) {
		slen[i] = strlen(sraw[i]);
		gen_prefix(sprefix[i], sraw[i]);
	}

	/*
	// Print prefixes
	for(i = 0; i < N; ++ i) {
		for(j = 0; j < slen[i]; ++ j)
			printf("%c ", sraw[i][j]);
		printf("\n");
		for(j = 1; j <= slen[i]; ++ j)
			printf("%d ", sprefix[i][j]);
		printf("\n");
	}
	*/

	// Remove inclusions && calc edge weights
	memset(svalid, 0x3f, sizeof(svalid));
	for(i = 0; i < N; ++ i)
		for(j = 0; svalid[i] && j < N; ++ j) if(j-i && svalid[j]) {
			kmp(prefix, sraw[j], sraw[i], sprefix[i]);
			/*
			for(printf("Test %d %d: ", i, j), k = 1; k <= slen[j]; ++ k)
				printf(" %d", prefix[k]); printf("\n");
				*/
			for(k = 1; k <= slen[j]; ++ k) if(prefix[k] == slen[i])
				break;
			if(k <= slen[j])
				svalid[i] = 0;
			graw[j][i] = prefix[slen[j]];
		}

	/*
	for(printf("svalid[] ="), i = 0; i < N; ++ i)
		printf(" %d", svalid[i]); printf("\n");
		*/

	for(i = 0, newN = 0; i < N; ++ i) if(svalid[i])
		s[newN ++] = i;
	N = newN;

	for(i = 0; i < N; ++ i) {
		for(j = 0; j < N; ++ j) {
			g[i][j] = (i-j)? graw[s[i]][s[j]] : 0;
			//printf("%d ", g[i][j]);
		}
		//printf("\n");
	}

	memset(_c, -1, sizeof(_c));
	memset(_prev, -1, sizeof(_prev));
	for(i = 0; i < N; ++ i)
		_c[i][1 << i] = 0;

	cmax = 0;
	for(i = 0; i < N; ++ i) if(c(i, (1 << N)-1) > cmax)
		cmax = c(i, (1 << N)-1), start= i;

	//printf("%d %d\n", cmax, start);

	freopen("adn.out", "w", stdout);
	int p = 0, cfg = (1 << N)-1;
	for(; cfg; start = i, cfg = j) {
		for(i = p; i < slen[s[start]]; ++ i)
			printf("%c", sraw[s[start]][i]);
		p = g[start][_prev[start][cfg]];
		i = _prev[start][cfg];
		j = cfg-(1 << start);
	}
	printf("\n");
	fclose(stdout);

	return 0;
}