ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

codevs-4189字典(字典树讲解+题目应用)

2021-06-05 19:08:52  阅读:223  来源: 互联网

标签:4189 rt int ++ skyzhong trie codevs 字典


字典

时间限制: 1 s
空间限制: 256000 KB

题目链接http://codevs.cn/problem/4189/

题目描述 Description
最经,skyzhong得到了一本好厉害的字典,这个字典里整整有n个单词(1<=n<=200000)

现在skyzhong需要在字典里查询以某一段字母开头的单词

如:skyzhong想查询a

那么只要是a开头的单词就可以了

skyzhong只想知道里面有没有这一个单词(因为没有他就不查了)

若有,请输出YES。若没有,请输出NO

输入描述 Input Description
第一行一个数n

第二行到第n+1行,一行一个字符串

再下一行一个数m,表示skyzhong想要查询的次数

接着m行,一行一个字符串,表示skyzhong想要查的东西

输出描述 Output Description
共m行,若有这字串输出YES,否则输出NO

样例输入 Sample Input
3

asd

asfdghj

asfd

3

asd

asdghj

asf

样例输出 Sample Output
YES

NO

YES

数据范围及提示 Data Size & Hint
字符串只有小写字母,且长度≤8


emmm。。。这是一道裸题,但这并不重要,下面的代码里并不会有注释,所以说只有大概明白我下面所讲内容的人才会看得明白。
首先我们对于一连串的字符串进行插入:
she
he
say
shr
her
接下来我们模拟字典树的插入过程,先建一个数组trie[i][j] ,其中i为下一个位置的标号,j为字符的数字代码(比如说将a转化为其ASCLL值-'a’就可以得到0-26个的小写字母。。。)首先判断是否首字母是否出现:由于我们是从1往下找到,所以第一个编号i=1时相当于第一层即根节点,我们设置一个标号tot(如下图所示),第一次she的进入后,这棵树就变成了(首先找到根节点,然后我们顺着根节点往下找就好了)
在这里插入图片描述

接下来放入he由于i=1时只找到了s,所以he就重新另起一头,将其标记为4
重复操作:在这里插入图片描述
接下来放入say:
在这里插入图片描述
之后就是shr:在这里插入图片描述
her:在这里插入图片描述

void insert(char *s,int rt) {
	for(int i=0; s[i]; i++) {
		int x=s[i]-'a';
		if(trie[rt][x]==0) {   //现在插入的字母在之前同一节点处未出现过
			trie[rt][x]=++tot;   //字母插入一个新的位置
		}
		rt=trie[rt][x];   //为下个字母的插入做准备
	}
}

如果上面的图解看明白了,那么这个插入的代码片段也就很清楚了。
之后就是查询,然而题目也说的很明白了,只要求查询以某一段字母开头的单词,所以我们直接从开始找到尾就行了。

int find(char *s,int rt) {
	for(int i=0; s[i]; i++) {
		int x=s[i]-'a';
		if(trie[rt][x]==0)return 0;//以rt为头结点的x字母不存在,返回0
		rt=trie[rt][x];//为查询下个字母做准备
	}
	return 1;
}

当然,这只是字典树,对于查找首字母并不存在第一层树中的单词是否出现过,如果只是单个查询的话KMP就可以解决了,如果是多模匹配的话就只能用AC自动机了。
接下来就是对以上模板的一个简单使用,题目如上所述就不多讲了,代码请看下面:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 2000010
using namespace std;
int tot=1,n;
int trie[maxn][26];
void insert(char *s,int rt) {
	for(int i=0; s[i]; i++) {
		int x=s[i]-'a';
		if(trie[rt][x]==0) {
			trie[rt][x]=++tot;
		}
		rt=trie[rt][x];
	}

}
int find(char *s,int rt) {
	for(int i=0; s[i]; i++) {
		int x=s[i]-'a';
		if(trie[rt][x]==0)return 0;
		rt=trie[rt][x];
	}
	return 1;
}
char s[22];
int main() {
	tot=0;
	int rt=0;
	scanf("%d",&n);
	for(int i=1; i<=n; i++) {
		scanf ("%s",s);
		insert(s,rt);
	}
	scanf("%d",&n);
	for(int i=1; i<=n; i++) {
		scanf ("%s",s);
		if(find(s,rt))printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

标签:4189,rt,int,++,skyzhong,trie,codevs,字典
来源: https://blog.51cto.com/u_15249461/2870435

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有