【字符串算法】字典树(Trie树)
什么是字典树
基本概念
字典树,又称为单词查找树或Tire树,是一种树形结构,它是一种哈希树的变种,用于存储字符串及其相关信息。

基本性质
1.根节点不包含字符,除根节点外的每一个子节点都包含一个字符
2.从根节点到某一节点。从根节点到该节点路径上经过的字符连接起来,就是该节点对应的字符串
3.同一个节点的所有子节点包含的字符都不相同
运用方面
典型应用是用于统计,排序和保存大量的字符串(不仅限于字符串),经常被搜索引擎系统用于文本词频统计。
优点缺点
字典树是经典的空间换时间的数据结构,利用字符串的公共前缀来减少查询时间,最大限度的减少无谓的字符串比较,查询效率据说比哈希树高。
但缺点就很显然了,就是空间比较大……
举个栗子
什么不太了解,没事,让我们来结合栗子来分析一下!
我们首先读入四个字符串
ba
b
band
abc
在没有读入前,我们有一个空空的根节点;

接着我们插入单词ba;

接着插入单词b,由于根节点有连向b的子节点,所以只需路径上的s++就好了;

接着插入单词bank,ba之前就有,只需s++,而nk需要在ba后添加子节点完成存储;

最后插入单词abc;

如何构造字典树
我们来结合程序一步一步来构造这棵可爱的字典树吧!!
构造节点
我们需要运用struct来存储字典树上每个节点的信息:
struct node
{
int s,v[27],val;
node()
{
s=0;
memset(v,-1,sizeof(v));
}
}t[410000];
s是用来存储有多少个单词进过了这个节点,v是用来存储这个点从a到z的儿子节点分别在哪,而val则是存储这个节点的权值,至于权值代表什么,就要依照题目灵活变换了。
构造字典树
我们先抛出程序:
int bt(int root)
{
int len=strlen(a+1);int x=root;
for(int i=1;i<=len;i++)
{
int y=a[i]-'a'+1;//将a^z转化为1^26
if(t[x].v[y]==-1)t[x].v[y]=++tot;
x=t[x].v[y];t[x].s++;
}
}
首先我们先读入了一个字符串a,它的长度为len;
接着我们对于它的字符进行循环处理,当我们处理到这个字符串的第i个字符的时候,我们要进行分类讨论——
我们用x存储第i-1个字符在字典树中的位置;
当我的前一个字符没有指向我的字符的时候,我就tot++,在字典树中开创一个新的空间,我就把自己放在这个空间里;如果我的前一个字符有指向我的字符的子节点时,我就放心地走到那个子节点就好了;最后记得更新x的值为当前处理的子节点的位置,并且s++,表示又多了一个单词进过了这个节点,以及完成val的修改之类的工作;
i++,进入下一重循环!
这样一棵完整的字典树就出来了!
模板&&模板题
【caioj 1463】统计前缀
题目描述
【题意】
给出很多个字符串(只有小写字母组成)和很多个提问串,统计出以某个提问串为前缀的字符串数量(单词本身也是自己的前缀).
【输入格式】
输入n,表示有n个字符串(n<=10000)
接下来n行,每行一个字符串,字符串度不超过10
输入m,表示有m个提问(m<=100)
第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
【输出格式】
对于每个提问,给出以该提问为前缀的字符串的数量.
【样例输入】
5
banana
band
bee
absolute
acm
4
ba
b
band
abc
【样例输出】
2
3
1
0
就是一道裸题,查询时输出对应节点的s就好了;
附上代码:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int s,v[27];
node()
{
s=0;
memset(v,-1,sizeof(v));
}
}t[410000];
char a[410000];
int i,j,k,m,n,tot,js,jl;
int bt(int root)
{
int len=strlen(a+1);int x=root;
for(int i=1;i<=len;i++)
{
int y=a[i]-'a'+1;
if(t[x].v[y]==-1)t[x].v[y]=++tot;
x=t[x].v[y];t[x].s++;
}
}
int solve(int root)
{
int len=strlen(a+1);int x=root;
for(int i=1;i<=len;i++)
{
int y=a[i]-'a'+1;
if(t[x].v[y]==-1)return 0;
x=t[x].v[y];
}
return(t[x].s);
}
int main()
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",a+1);
bt(0);
}
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",a+1);
printf("%d\n",solve(0));
}
}
结语
通过这篇BLOG相信你已经掌握了Trie树,那就向着AC自动机前进吧!希望你喜欢这篇BLOG!
字典树练习题:
HDU1251(本题原版)
HDU1075
HDU1800
参考
https://ethsonliu.com/2019/09/trie-tree.html
https://oi-wiki.org/string/trie/
【字符串算法】字典树(Trie树)的更多相关文章
- 字典树(Trie树)的实现及应用
>>字典树的概念 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树.与二叉查找树不同,Trie树的 ...
- [POJ] #1002# 487-3279 : 桶排序/字典树(Trie树)/快速排序
一. 题目 487-3279 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 274040 Accepted: 48891 ...
- Atitit 常见的树形结构 红黑树 二叉树 B树 B+树 Trie树 attilax理解与总结
Atitit 常见的树形结构 红黑树 二叉树 B树 B+树 Trie树 attilax理解与总结 1.1. 树形结构-- 一对多的关系1 1.2. 树的相关术语: 1 1.3. 常见的树形结构 ...
- 【HDU - 5790 】Prefix(主席树+Trie树)
BUPT2017 wintertraining(15) #7C 题意 求[min((Z+L)%N,(Z+R)%N)+1,max((Z+L)%N,(Z+R)%N)+1]中不同前缀的个数,Z是上次询问的结 ...
- 洛谷$P4585\ [FJOI2015]$火星商店问题 线段树+$trie$树
正解:线段树+$trie$树 解题报告: 传送门$QwQ$ $umm$题目有点儿长我先写下题目大意趴$QwQ$,就说有$n$个初始均为空的集合和$m$次操作,每次操作为向某个集合内加入一个数$x$,或 ...
- luoguP6623 [省选联考 2020 A 卷] 树(trie树)
luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...
- [转载]字典树(trie树)、后缀树
(1)字典树(Trie树) Trie是个简单但实用的数据结构,通常用于实现字典查询.我们做即时响应用户输入的AJAX搜索框时,就是Trie开始.本质上,Trie是一颗存储多个字符串的树.相邻节点间的边 ...
- 字典树(Trie树)实现与应用
一.概述 1.基本概念 字典树,又称为单词查找树,Tire数,是一种树形结构,它是一种哈希树的变种. 2.基本性质 根节点不包含字符,除根节点外的每一个子节点都包含一个字符 从根节点到某一节点.路径上 ...
- 字典树 trie树 学习
一字典树 字典树,又称单词查找树,Trie树,是一种树形结构,哈希表的一个变种 二.性质 根节点不包含字符,除根节点以外的每一个节点都只包含一个字符: 从根节点到某一节点,路径上经过的字符串连接起 ...
随机推荐
- go语言基础实例
一:变量 1)变量声明 func main() { var v1 int var v2 int //一次声明多个变量 var ( v3 int v4 int ) //变量最开始会有一个零值 fmt.P ...
- 从后端到前端之Vue(六)表单组件
表单组件 做项目的时候会遇到一个比较头疼的问题,一个大表单里面有好多控件,一个一个做设置太麻烦,更头疼的是,需求还总在变化,一会多选.一会单选.一会下拉的,变来变去的烦死宝宝了. 那么怎么解决这个问题 ...
- 【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
写在前面 最近,二狗子入职了新公司,新入职的那几天确实有点飘.不过慢慢的,他发现他身边的人各个身怀绝技啊,有Spring源码的贡献者,有Dubbo源码的贡献者,有MyBatis源码的贡献者,还有研究A ...
- oa项目面试准备
熟悉项目在ssm框架下的编程流程,了解mysql html spring springmvc mybatis技术.了解过springboot编程. 在上个寒假跟着培训机构用springboot框架编写 ...
- 期望概率DP
期望概率DP 1419: Red is good Description 桌面上有\(R\)张红牌和\(B\)张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付 ...
- 常用mac命令
~/.bash_profile 可以添加常用的一些命令别名alias unity="open -n /Applications/Unity/Unity.app"
- web前端笔记(包含php+laravel)
概况 熟悉HTML5.CSS3.JavaScript.ES6规范 熟悉JQuery框架 熟悉BootStrap 熟悉Less.Sass 熟悉Vue 熟悉Git postman Bootstrap 布局 ...
- JVM学习第三天(JVM的执行子系统)之开篇Class类文件结构
虽然这几天 很忙,但是学习是不能落下的,也不能推迟,因为如果推迟了一次,那么就会有无数次;加油,come on! Java跨平台的基础: 各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节 ...
- Zabbix Agent日志路径定位
Zabbix Agent的日志一般记录在zabbix_agentd.log中,那么如何定位.找到Zabbix Agent的日志路径呢? 下面从Linux操作系统和Windows系统来简单总结一下,方便 ...
- [LeetCode]105. 从前序与中序遍历序列构造二叉树(递归)、108. 将有序数组转换为二叉搜索树(递归、二分)
题目 05. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 题解 使用HashMap记录当前子树根节点在中序遍历中的位置,方便每次 ...