【字符串算法】字典树Trie入门

基本概念

顾名思义,字典树(也叫前缀树)就是可以像字典那样来保存一些单词的集合。

如图所示:

(图片来自OIWiKi)

设根节点的标号为$0$,然后其余结点依次编号;我们用数组来存每个节点的所有子节点

更具体地,设数组$ch[MaxNode][SigmaSize]$,其中$MaxNode$表示最大可能的节点个数,$SigmaSize$是字符集合。$ch[i][j]$表示结点标号为$i$的结点 的 字母编号为$j$(比如说,j=字母-‘a‘)的子节点的结点标号。如果$ch[i][j]$为$0$,则表示$i$没有字母编号为$j$的子节点。

操作-插入

插入的时候,直接从根节点开始遍历,根据要插入的字符串往下面走,如果碰到没有的字符就新插入结点就可以了。

scanf("%s",s+1);
//插入字符串 这颗trie根节点是从1开始的
int u=1,len=strlen(s+1);
for(int j=1;j<=len;j++)
{
    int c=s[j]-‘a‘;
    if(!ch[u][c])//原本没有这个字符
        ch[u][c]=++tot;//插入这个字符
    u=ch[u][c];
}

操作-查询

查询与操作是相似的,这里不再赘述。

不过要注意,在字典树里面可以查找到的不一定就是单词,还有可能是单词的前缀。

比如说字典树里面有一个单词为$apple$,查询$app$时在字典树里面会查到它,但是它只是一个前缀,不是单词。

所以我们还需要再添加一个标记数组$tag[i]$表示节点标号为$i$的结点是否为一个单词的结尾,我们把这个节点叫做单词结点。显而易见,我们之前的那个插入就要改一下了。

同样的,这个标记数组还可以干一些别的事情,比如在字符串被附了权值的情况下存这个字符串(以当前结点结尾的字符串)的权值。

scanf("%s",s+1);
int u=1,len=strlen(s+1);
for(int j=1;j<=len;j++)
{
    int c=s[j]-‘a‘;
    u=ch[u][c];
    if(!u) break;//不存在
}
if(tag[u]==0) ...  //不存在 

操作-删除

其实直接把单词结点的标记清掉就可以了。

但是呢,也可以针对特殊情况特殊处理一下。

分类讨论一下:

  1. 那么直接把整个单词全部删掉就可以了。(清$ch[][]$
  2. 如果被删除单词的那条链上某处有了分支,然后那个分支应该是有一支是表示被删除单词的,其他的都不是,那么删掉这一支就可以了(清$ch$

其实还是有些麻烦,还不如直接清标记...

例题 & 模板

于是他错误的点名开始了

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 #define N 500005
 8 int ch[N][26];//结点i的为j+‘a‘子节点的节点标号
 9 char s[55];
10 int n,m,tag[N],tot=1;
11 int main()
12 {
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++)
15     {
16         scanf("%s",s+1);
17         //插入字符串 这颗trie根节点是从1开始的
18         int u=1,len=strlen(s+1);
19         for(int j=1;j<=len;j++)
20         {
21             int c=s[j]-‘a‘;
22             if(!ch[u][c])//原本没有这个字符
23                 ch[u][c]=++tot;//插入这个字符
24             u=ch[u][c];
25         }
26         tag[u]=1;//标记这个结点是单词结点
27         //---
28     }
29     scanf("%d",&m);
30     while(m--)
31     {
32         scanf("%s",s+1);
33         int u=1,len=strlen(s+1);
34         for(int j=1;j<=len;j++)
35         {
36             int c=s[j]-‘a‘;
37             u=ch[u][c];
38             if(!u) break;//名字不存在
39         }
40         if(tag[u]==1)
41         {
42             puts("OK");
43             tag[u]=2;
44         }
45         else if(tag[u]==2)
46             puts("REPEAT");
47         else puts("WRONG");
48     }
49     return 0;
50 }

后记

做了例题之后,发现$Trie$干的事情$map$也能干,$Hash$也能干,不就是存个单词,查个单词嘛!

别急,他还有很多用法...检索字符串只是最基本的操作而已...

原文地址:https://www.cnblogs.com/lyttt/p/12219609.html

时间: 2024-10-01 04:24:55

【字符串算法】字典树Trie入门的相关文章

字典树Trie树

一.字典树 字典树--Trie树,又称为前缀树(Prefix Tree).单词查找树或键树,是一种多叉树结构. 上图是一棵Trie树,表示了关键字集合{"a", "to", "tea", "ted", "ten", "i", "in", "inn"} .从上图可以归纳出Trie树的基本性质: 1. 根节点不包含字符,除根节点外的每一个子节点都包含一

[POJ] #1003# 487-3279 : 桶排序/字典树(Trie树)/快速排序

一. 题目 487-3279 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 274040   Accepted: 48891 Description Businesses like to have memorable telephone numbers. One way to make a telephone number memorable is to have it spell a memorable word or

字典树Trie

字典树Trie Trie,又称字典树,前缀树(prefix tree),是一种树形结构,用于保存大量的字符串. 它的优点是:利用字符串的公共前缀来节约存储空间.查找.插入复杂度为O(n),n为字符串长度. 它有3个基本性质: 1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符. 2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串. 3. 每个节点的所有子节点包含的字符都不相同. 假设有abc,abcd,abd, b, bcd,efg,hii这7个单词,可构建字典树

字典树 Trie (HDU 1671)

Problem Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers: 1. Emergency 911 2. Alice 97 625 999 3. Bob 91 12 54 26 In this

HDU 1247 Hat&#39;s words(字典树Trie)

解题思路: 判断给出的单词是否恰好由另外两个单词组成,用栈保存每个子字符串的节点,从这个节点出发判断剩下的字符串是否在字典树中即可. #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <map> #include <sta

『字典树 trie』

字典树 (trie) 字典树,又名\(trie\)树,是一种用于实现字符串快速检索的树形数据结构.核心思想为利用若干字符串的公共前缀来节约储存空间以及实现快速检索. \(trie\)树可以在\(O((n+m)*len)\)解决形如这样的字符串检索问题: 给定\(n\)个字符串,再给定\(m\)个询问,每次询问某个字符串在这\(n\)个字符串中出现了多少次 特点 \(trie\)树最显著的特点是,当它存储的若干个字符串有公共前缀时,它将不会重复存储. 与其他树形数据结构不同的是,\(trie\)树

【数据结构】字典树/Trie树/前缀树 - 字符串的统计、排序和保存

字典树 描述 字典树,又称单词查找树.Trie树.前缀树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计.排序和保存大量的字符串(但不仅限于字符串). 常见操作有插入和查找,删除操作少见. 性质 根节点不包含字符 除根节点外每一个节点都只包含一个字符 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串 每个节点的所有子节点包含的字符都不相同 优点 利用字符串的公共前缀来减少查询时间 最大限度地减少无谓的字符串比较 查询效率比哈希树高 自带字典序排序 直接判断重复,或者记

[转载]字典树(trie树)、后缀树

(1)字典树(Trie树) Trie是个简单但实用的数据结构,通常用于实现字典查询.我们做即时响应用户输入的AJAX搜索框时,就是Trie开始.本质上,Trie是一颗存储多个字符串的树.相邻节点间的边代表一个字符,这样树的每条分支代表一则子串,而树的叶节点则代表完整的字符串.和普通树不同的地方是,相同的字符串前缀共享同一条分支.还是例子最清楚.给出一组单词,inn, int, at, age, adv, ant, 我们可以得到下面的Trie: 可以看出: 每条边对应一个字母. 每个节点对应一项前

字典树(Trie Tree)

在图示中,键标注在节点中,值标注在节点之下.每一个完整的英文单词对应一个特定的整数.Trie 可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的.键不需要被显式地保存在节点中.图示中标注出完整的单词,只是为了演示 trie 的原理. trie 中的键通常是字符串,但也可以是其它的结构.trie 的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列.比如,bitwise trie 中的键是一串位元,可以用于表示整数或者内存地址. Trie树是一种树形结