hdu 1251 统计难题 字典树裸题

题目链接


思路:



经典的字典树问题,字典树最基本的插入和查询操作.

字典树最最最基本的应用就是查询以某一个单词为前缀的单词的数量,有两种模板,一种是静态的一种是动态的,一般用静态的就好.


动态模板

#include
#include
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e5+10;
struct Trie{
	Trie *next[26];//next是表示每层有多少种类的数,如果只是小写字母,则26即可,	
				  //	若改为大小写字母,则是52,若再加上数字,则是62了,这里根据题意来确定。 
	int num;
//num可以表示一个字典树到此有多少相同前缀的数目,这里根据需要应当学会自由变化。

	Trie()
	{
		int i;
		for(int i=0;i<26;i++)
		next[i]=NULL;
		num=0;
	 } 
	
}root;
void insert(char s[])//将字符串s插入到字典树中
{
	Trie *p=&root;
	int i;
	for(int i=0;s[i];i++)//遍历s的每一个字符 
	{
		if(p->next[s[i]-'a']==NULL) //如果没有该字符对应的节点 
		p->next[s[i]-'a']=new Trie;
		p=p->next[s[i]-'a'];
		p->num++; 
	}
 } 
int find(char s[])//返回以字符串s为前缀的单词的数量
{
	Trie *p=&root;
	int i;
	for(int i=0;s[i];i++)//在字典树找到该单词的结尾位置
	{
		if(p->next[s[i]-'a']==NULL)
		return 0;
		p=p->next[s[i]-'a']; 
	}
	return p->num;
}
int main(){
	
	char s[20];
	while(gets(s))
	{
		if(strlen(s)==0||s[0]==NULL)
		break;
		insert(s);
	}
	while(~scanf("%s",s))
	{
		printf("%d\n",find(s));
	}
	return 0;
}




静态模板: 数组模拟


#include
#include
#include
#include 
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e6+10;
int trie[maxn][26];
//数组形式定义字典树,值存储的是下一个字符的位置
int num[maxn]={0};
//附加值,以某一字符串为前缀的单词的数量 
int pos=1; 
void insert(char s[])//在字典树中插入单词s
{
	int c=0;
	for(int i=0;s[i];i++)
	{
		int n=s[i]-'a';
		if(trie[c][n]==0)//如果对应字符还没有值
			trie[c][n]=pos++;
		c=trie[c][n];
		num[c]++; 
	 } 
} 
int find(char s[])//返回以某个字符串为前缀的单词的数量
{
	int c=0;
	for(int i=0;s[i];i++)
	{
		int n=s[i]-'a';
		if(trie[c][n]==0)
		return 0;
		c=trie[c][n];
	 } 
	 return num[c];
} 
int main(){

	char s[20];
	while(gets(s))
	{
		if(strlen(s)==0||s[0]==NULL)
		break;
		insert(s);
	}
	while(~scanf("%s",s))
	{
		printf("%d\n",find(s));
	}
	return 0;
}





你可能感兴趣的:(字典树)