HDU 1247 trie 一个单词是否是两个单词的连接

3 篇文章 0 订阅
#include <iostream>  
using namespace std;  

char list[50001][26];  
const int kind = 26;  
int cnt = 0;  

struct Treenode  
{  
	bool flag;  
	Treenode *next[kind];  
	Treenode()  
	{  
		flag = false;  
		for ( int i = 0; i < kind; ++i )  
			next[i] = NULL;  
	}  
} node[100000];  //静态trie

void Insert ( Treenode *&root, char *word )  
{  
	Treenode *location = root;  
	if ( location == NULL )  
	{  
		location = &node[cnt++];  
		root = location;  
	}  

	int id, i = 0;  
	while ( word[i] )  
	{  
		id = word[i] - 'a';  
		if ( location->next[id] == NULL )  
			location->next[id] = &node[cnt++];  
		location = location->next[id];  
		++i;  
	}  
	location->flag = true; /*注意标记单词的最后一个字母,说明在这之前的字母组成一个单词,以便查询时划分*/  
}  

bool check ( Treenode *root, char* word )  
{  
	Treenode *location = root;  
	if ( location == NULL ) return false;  

	int id, i = 0, len = strlen(word);  
	while ( word[i] )  
	{  
		id = word[i] - 'a';  
		if ( location->next[id] == NULL )  
			return false;  
		if ( i == len-1 && location->next[id]->flag == true )  
			return true;/*查找到最后一个字符时,节点的标记应该是true,这样才是完全匹配的*/  
		location = location->next[id];  
		++i;  
	}  
	return false;  
}  

bool Search ( Treenode *root, char * word )  
{  
	Treenode *location = root;  
	if ( location == NULL ) return false;  

	int id, i = 0, len = strlen(word);  
	while ( word[i] )  
	{  
		id = word[i] - 'a';  
		if ( location->next[id] == NULL )  
			return false;  
		if ( location->next[id]->flag == true )/*当检测到一个标记时说明单词的前半部分已经检测到,现在只需检测后面一部分是否能由另一个单词构成*/  
		{  
			if ( i + 1 < len && check(root,&word[i+1]) )  
				return true;  
		}  
		location = location->next[id];  
		++i;  
	}  
	return false;  
}  

int main()  
{  
	int i = 0, j;  
	Treenode *root = NULL;  
	while ( scanf("%s", list[i]) != EOF )  
	{  
		Insert(root,list[i]);  
		++i;  
	}  

	for ( j = 0; j < i; ++j )  //将单词保存在list再搜索一遍
	{  
		if ( Search(root,list[j]) )  
			printf("%s\n",list[j]);  
	}  
	return 0;  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值