杭电ACM——1251,统计难题(Trie树)

此题为Trie树(字典树)的模板题。
Trie树的概念、性质及讲解可参考该博客:
https://www.cnblogs.com/xujian2014/p/5614724.html

本题采用了静态的模板,只用数组进行操作。
代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=1e6+5;	//表示节点总数(要足够大)
int Trie[maxn][26];	//Trie[i,j]表示第i个节点通过路径j到达的节点编号
int num[maxn]={0};	//num[i]表示节点的属性(Trie数的节点是空的,其属性得依据题意来定),在此表示以该字符串为前缀的单词个数
char s[11];
int tot=1;	//表示节点的个数
void insert()			//插入
{
	int len=strlen(s);
	int node=0;	//node表示节点的编号,node=0,其实也就是根,从根开始搜索
	int i,side;	//side表示边(路径)
	for(i=0;i<=len-1;i++)
	{
		side=s[i]-'a';
		if(Trie[node][side]==0)		//等于0说明这个字母还没有插入,就得进行插入操作
			Trie[node][side]=tot++;
		node=Trie[node][side];	//转换节点,继续搜索
		num[node]++;		//以该串为前缀的单词数+1
	}
}
int inquire()		//询问以某个串为前缀的单词数
{
	int len=strlen(s);
	int node=0;		//依旧从根开始
	int i,side;
	for(i=0;i<=len-1;i++)
	{
		side=s[i]-'a';
		if(Trie[node][side]==0)			//等于0就说明所建立的Trie树没有保存这个串,直接返回0即可
			return 0;
		node=Trie[node][side];		//否则,转换节点,继续搜索
	}
	return num[node];		
}
int main()
{
	int ans;
	while(gets(s))		//这里运用了一个输入的技巧,gets可以读取一个空行,且会把'\n'转化为'\0'
	{
		if(s[0]=='\0')
			break;
		insert();
	}
	while(~scanf("%s",s))
	{
		ans=inquire();
		printf("%d\n",ans);
	}
	return 0;
}

这道题要好好消化,很有帮助。今后还会写一下动态的模板(等我学会了。。。)

猜你喜欢

转载自blog.csdn.net/shamansi99/article/details/89423680