您的位置:首页 > 其它

HDU 1671 Phone List (字典树入门基础题)

2014-07-16 15:42 423 查看
题目链接:HDU 1671 Phone List

题意:判断所给的字符串中是否存在一个字符串是其他任意字符串的前缀。

刚学字典树。

注意初始化,

AC代码:

#include<stdio.h>
#include<string.h>
#define Word_Len 100002
#define Sigma_size 30

struct Trie
{ 
	int ch[Word_Len][Sigma_size]; //Word_Len是字典树的节点数 若都是小写字母Sigma_size=26
	int Have_word[Word_Len];      //这个节点下有几个单词
	int value[Word_Len];          // 这个节点附带的信息,初始化为0表示这个节点不存在单词,所以节点带的信息必须!=0
	int sz;                           //当前节点数
	void init()  //初始化字典树
	{
		sz=1;
		memset(ch[sz],0,sizeof ch[sz]);
		memset(Have_word,0,sizeof Have_word);
		memset(value,0,sizeof value);
	}
	int idx(char c) //字符串编号
	{
		return c-'0';
	}
	void build(char s[])
	{
		int i;
		int u=0;
		int len=strlen(s);
		for(i=0;i<len;i++)
		{
			int c=idx(s[i]);
			if(!ch[u][c]) //节点不存在就新建后附加
			{
				memset(ch[sz],0,sizeof ch[sz]);
				value[sz]=0;
				ch[u][c]=sz++;
			}
			u=ch[u][c]; //u等于下前一个字母的节点
			value[u]=c;
			Have_word[u]++; //现在的u就是这个单词的最后一个位置
		}
	}
	int find_word(char s[])
	{
		int i;
		int u=0;
		int len=strlen(s);
		for(i=0;i<len;i++)
		{
			int c=idx(s[i]);
			if(!ch[u][c]) 	//节点不存在
				return 0;
			u=ch[u][c];
		}
		return Have_word[u];
	}
};
Trie ac;

char num[50010][20];

int main()
{
	int t;
	int i,n;
	
	while(scanf("%d",&t)!=EOF)
	{
		while(t--)
		{	
			ac.init();
			scanf("%d",&n);
			for(i=0;i<n;i++)
			{
				scanf("%s",num[i]);
				ac.build(num[i]);
			}
			for(i=0;i<n;i++)
			{
				int ans=ac.find_word(num[i]);
//				printf("(%d)\n",ans);
				if(ans>1)
					break;
			}
			if(i<n)
				printf("NO\n");
			else
				printf("YES\n");
			
			for(i=0;i<n;i++)
				memset(ac.ch[i],0,sizeof ac.ch[i]);//初始化,刚开始没考虑到
		}
	}
return 0;
}

/*
10
2
111
112
2
111
1112

*/


反思:程序的初始化很关键,没做好初始化,跑多个案例,答案天差地别。学习一些算法刚开始可以采用黑箱方法,前提是原理要明白。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: