首页 > 代码库 > POJ 3080 Blue Jeans Trie后缀树解法

POJ 3080 Blue Jeans Trie后缀树解法

题目是牛仔裤的意思,不过看不出题意和Blue Jeans有什么关系。

本题的数据是很水的,数据量小,故此可以使用非常暴力的方法过,也可以使用不那么暴力的KMP过。

这里使用更加不暴力的Trie后缀树过,这种解法就一点都不水了,呵呵。

思路:

1 建立所有字符串的后缀Trie树

2 增加额外信息,看每过路径是否是所有的字符串都经过了,如果是,那么就是合法的字符串了,查找最长的这样的字符串

3 优化一下:如果不是所有字符串的经过的路径,那么就可以直接返回,不往下搜索了

最后,我发现删除Trie都是很耗时的,不释放Trie那么速度是快很多的,需要内存自然高很多。


#include <stdio.h>
#include <string.h>

const int MAX_N = 61;
const int ALP_LEN = 4;
const int SIGNIFICANT = 3;
char DNAStr[MAX_N];

inline int charToint(char a)
{
	switch (a)
	{
	case 'A':
		return 0;
	case 'T':
		return 1;
	case 'G':
		return 2;
	case 'C':
		return 3;
	}
	return -1;//unexpected input
}

inline char intTochar(int i)
{
	switch (i)
	{
	case 0:
		return 'A';
	case 1:
		return 'T';
	case 2:
		return 'G';
	case 3:
		return 'C';
	}
	return '?';//unexpected input
}

struct Node
{
	int n, tab;
	Node *alpha[ALP_LEN];
	Node():n(0), tab(-1)
	{
		for (int i = 0; i < ALP_LEN; i++)
		{
			alpha[i] = NULL;
		}
	}
};

void delTrie(Node *rt)
{
	if (rt)
	{
		for (int i = 0; i < ALP_LEN; i++)
		{
			if (rt->alpha[i]) delTrie(rt->alpha[i]);
			rt->alpha[i] = NULL;
		}
		delete rt;
	}
}

Node *Trie;
int tab;
void insert(char *chs, int len)
{
	Node *pCrawl = Trie;
	for (int i = 0; i < len; i++)
	{
		int k = charToint(chs[i]);
		if (!pCrawl->alpha[k]) pCrawl->alpha[k] = new Node;
		pCrawl = pCrawl->alpha[k];
		if (pCrawl->tab != tab)//防止重复计算
		{
			pCrawl->tab = tab;
			pCrawl->n++;
		}
	}
	if (pCrawl->tab != tab)
	{
		pCrawl->tab = tab;
		pCrawl->n++;
	}
}

int maxLen, pid, n;
char path[MAX_N], res[MAX_N];
void search(Node *rt)
{
	for (int i = 0; i < ALP_LEN; i++)
	{
		if (rt->alpha[i] && rt->alpha[i]->n == n)
		{
			path[pid++] = intTochar(i);
			if (maxLen < pid)
			{
				maxLen = pid;
				path[pid] = '\0';
				strncpy(res, path, pid+1);
			}
			search(rt->alpha[i]);
			pid--;
		}
	}
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		Trie = new Node;
		scanf("%d", &n);
		getchar(); // get rid of '\n'
		tab = 0;
		for (int i = 0; i < n; i++)
		{			
			gets(DNAStr);
			int len = MAX_N-1;
			tab++;
			for (char *p = &DNAStr[0]; *p; p++)
			{
				insert(p, len);
				len--;
			}
		}
		maxLen = 0, pid = 0;
		search(Trie);

		if (maxLen < SIGNIFICANT)
		{
			puts("no significant commonalities");
		}
		else
		{
			printf("%s\n", res);
		}

		//delTrie(Trie);
	}
	return 0;
}