HDU 1251 统计难题 (字典树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251


题面:

统计难题

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 25921    Accepted Submission(s): 10560


Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
 

Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

注意:本题只有一组测试数据,处理到文件结束.
 

Output
对于每个提问,给出以该字符串为前缀的单词的数量.
 

Sample Input
   
   
   
   
banana band bee absolute acm ba b band abc
 

Sample Output
   
   
   
   
2 3 1 0

题意:

   额,中文大家都懂。


解题:

    字典树裸题,val值统计经过该点的字母数量。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
struct Trie
{
	//用来储存该节点的26个字母下标,ch的第一维要注意,要开大,不然会T 
	int ch[1000010][26];
	//val数组一般用来存储权值,视题目灵活运用,sz是当前节点数量
	int val[1000010],sz;
	//初始化
	void init()
	{
		sz=1;
		memset(ch[0],0,sizeof(ch[0]));
	}
	//插入一条单词
	void insert(string s)
	{
		//u是节点编号,并不是层数
		int u=0,len=s.length();
		for(int i=0;i<len;i++)
		{
			//取下标
			int c=(s[i]-'a');
			//如果该节点不存在,创建该节点
			if(!ch[u][c])
			{
				//真的是相当的省
				memset(ch[sz],0,sizeof(ch[sz]));
				//因为刚创建所以为1
				val[sz]=1;
				//给该节点分配编号
				ch[u][c]=sz++;
				//下移
				u=ch[u][c];
			}
			//已经存在了
			else
			{
			  //下移,并计数值加一
			  u=ch[u][c];
		      val[u]++;
			}
		}
	}
	//查询前缀
	int query(string s)
	{
		int len=s.length(),u=0,c;
		//不断下移,直至移到给定的前缀的最后一个单词
		bool sign=true;
		for(int i=0;i<len;i++)
		{
		   c=s[i]-'a';
		   if(ch[u][c])
             u=ch[u][c];
           else
           {
              sign=false;
              break;
           }
		}
		if(sign)
          return val[u];
        else
          return 0;
	}
};
Trie T;
int main()
{
        string s;
        T.init();
        while(getline(cin,s))
        {
           if(s=="")break;
           T.insert(s);
        }
        while(getline(cin,s))
        {
           cout<<T.query(s)<<endl;
        }
	    return 0;
}


你可能感兴趣的:(数据结构,入门,字典树)