44、【树和二叉树】Trie(前缀树/搜索树)字符串统计(C/C++版)

介绍

在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。

trie中的键通常是字符串,但也可以是其它的结构。trie的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie中的键是一串位元,可以用于表示整数或者内存地址。
在这里插入图片描述

基本性质

  1. 根节点不包含字符,除根节点外,每个节点只包含一个字符。

  2. 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。

  3. 每个节点的所有子节点包含的字符串不相同。

应用场景:
(1)字符串检索;(2)文本预测、自动完成,see also,拼写检查;(3)词频统计;(4)排序;(5)字符串最长公共前缀;(6)字符串搜索的前缀匹配

参考文章:Trie(前缀树/字典树)及其应用

实战例题

维护一个字符串集合,支持两种操作:

I x 向集合中插入一个字符串 x;
Q x 询问一个字符串在集合中出现了多少次。

共有 N个操作,输入的字符串总长度不超过 105,字符串仅包含小写英文字母。

输入格式

第一行包含整数 N,表示操作数。接下来 N行,每行包含一个操作指令,指令为 I x 或 Q x 中的一种。

输出格式

对于每个询问指令 Q x,都要输出一个整数作为结果,表示 x在集合中出现的次数。每个结果占一行。

数据范围

1≤N≤2∗104

输入样例:

5
I abc
Q abc
Q ab
I ab
Q ab

输出样例:

1
0
1

算法实现

#include <stdio.h>

const int N = 1e5 + 10;

// N个结点,26个空间中对应26个不同的英文字母,每个空间中对应所连子结点的下标
int son[N][26];
// cnt[i]记录,当到达下标为i的结点时,已被标记的单词数量(不是字母数量)
int cnt[N];
// 记录当前存储空间可用于存储结点的下标
int idx;

void insert(char str[]){
    int p = 0;
    for(int i = 0; str[i] != '\0'; i++){
        int u = str[i] - 'a';       // 归一化为0~25的数字来表示a~z
        if(!son[p][u])      son[p][u] = ++idx;      // 下标为0的点为根节点
        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];
}

int main(){
    int n;      scanf("%d", &n);
    char str[N];
    while(n--){
        // 避免读入时读取空格,因此设置为字符串形式
        char op[2];     scanf("%s%s", &op, &str);
        if(op[0] == 'I')        insert(str);
        else                    printf("%d\n", query(str));
    }

    return 0;
}

当所有字符串长度之和为n,构建字典树的时间复杂度为O(n)

但要查找的字符串长度为k,查找的时间复杂度为O(k)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辰阳星宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值