Trie树及模板

发布时间 2023-08-31 23:45:33作者: gao79138

Trie树及模板

1.Trie树介绍

    Trie树又称字典树(单词查找树),是用来高效地存储和查找字符串集合的数据结构。

2. Trie树的操作

img
img
img
img
img
img

    我们假设要用Trie树来存储上述的字符串,那么过程如下:
    1.  首先,我们需要创建Trie树的根节点。创建之后存储abcdef字符串。首先,从前往后遍历这样的字符串。根节点中并不存在a这个子节点,那么创建。a这个子节点并不存在b这个子节点,那么创建....直到建成上述图片那样为止。
    2.  存储下一个单词,首先需要看根节点是否有a这个子节点。发现有,因此不需要创建。再看a这个子节点是否有b这个子节点。发现有,不需要创建。再看b这个子节点是否有d这个子节点。发现没有,创建d节点....直到建成上述图片为止。
    3.  按照上述的步骤创建其他单词即可。结果会在上面依次展示。
    4.  需要注意的是,每往Trie树添加完一个单词后,我们都需要在该单词的末尾添加一个标记,代表这是一个单词。结果如上图所示。

img

    那么,我们如何利用Trie树来查找字符串呢?过程如下:
    1.  假设,我们需要查找aced这个单词。首先,从根节点开始,依次找寻a、c、e、d节点,发现都存在。并且,在d的末尾我们发现了一个标记,代表Trie树中存在以d结尾的单词,即:aced。
    2.  接下来,我们查找abcf这个单词。发现,a、b、c节点均存在。但是,c节点没有f这个子节点。因此,在Trie树中不存在abcf这个单词。如上图所示。
    3.  接下来,我们查找abcd这个单词。在查找过程中,我们发现:虽然存在a、b、c、d这四个节点。但是,d的末尾并没有标记,代表Trie树中不存在以d结尾的单词(指:abcd)。因此,在Trie树中不存在abcd这个单词。如上图所示。
    以上就是Trie树存储和查找的过程。

3. Trie树模板

int son[N][26], cnt[N], idx;
// 0号点既是根节点,又是空节点
// son[][]存储树中每个节点的子节点
// cnt[]存储以每个节点结尾的单词数量

// 插入一个字符串
void insert(char *str)
{
    int p = 0;
    for (int i = 0; str[i]; i ++ )
    {
        int u = str[i] - 'a';
        if (!son[p][u]) son[p][u] = ++ idx;
        p = son[p][u];
    }
    cnt[p] ++ ;
}

// 查询字符串出现的次数
int query(char *str)
{
    int p = 0;
    for (int i = 0; str[i]; i ++ )
    {
        int u = str[i] - 'a';
        if (!son[p][u]) return 0;
        p = son[p][u];
    }
    return cnt[p];
}

4. 例题

https://www.acwing.com/problem/content/837/
#include <iostream>
#include <cstdio>

using namespace std;

const int N = 100010;

//代表Trie树节点
int son[N][26];
//用于统计单词的数量
int cnt[N];
//代表当前用到了哪个节点
//0号节点既是根节点也是空节点
int idx = 0;

void insert(char str[]){
    int p = 0;   //从根节点开始
    for(int i=0;str[i];i++){
        //完成从字母a-z=>0-25的映射
        int number = str[i] - 'a';
        //如果节点不存在
        if(!son[p][number]){
            //创建
            son[p][number] = ++idx;
        }
        //当前节点往下走
        p = son[p][number];
    }
    //当添加完单词之后,统计个数(添加标记)
    cnt[p]++;
}

int query(char str[]){
    int p = 0;
    for(int i=0;str[i];i++){
        int number = str[i] - 'a';
        if(!son[p][number]){
            return 0;
        }
        p = son[p][number];
    }
    return cnt[p];
}

int main(){
    int n;
    char op[2];
    char str[N];
    scanf("%d",&n);
    while(n--){
        scanf("%s%s",op,str);
        if(op[0] == 'I'){
            insert(str);
        }else{
            printf("%d\n",query(str));
        }
    }
    return 0;
}
    作者:gao79138
    链接:https://www.acwing.com/
    来源:本博客中的截图、代码模板及题目地址均来自于Acwing。其余内容均为作者原创。
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。