Trie树之字符串统计问题

         这是C++算法基础-数据结构专栏的第二十七篇文章,专栏详情请见此处


引入

        Trie树,即字典树,顾名思义,就是用类似字典的方式存储数据,而Trie树最经典也是最简单的一个应用就是字符串统计问题。

        字符串统计问题就是维护一个字符串集合,并支持两种操作:向集合中插入一个字符串和询问一个字符串在集合中出现了多少次。

        下面我们就来讲Trie树之字符串统计问题的实现。

定义

        Trie树,即字典树,顾名思义,就是用类似字典的方式存储数据,它是AC自动机的主要组成部分,它的最经典应用是字符串统计问题和最大异或对问题。

过程

        例题

        题目大意:维护一个字符串集合,并支持两种操作:向集合中插入一个字符串和询问一个字符串在集合中出现了多少次。

        算法

        对于Trie树,每道题会有相对应的一种存储方式,而在这一题中,我们建立一棵树,用点来代表字母,而从根结点到树上某一结点的路径就代表了一个字符串。

        具体来说,我们定义一个数组son[][]存储树中每个节点的子节点,其中数组的一维表示节点的编号,二维的数字代表了这条边在字母表中的次序(例如son[5][3]表示5号节点连接了字符c的节点编号);然后,为了方便识别Trie树中每个字符串的结尾处,我们在相应的节点打上标记并累计,所以我们开一个数组cnt[];最后,还需要一个变量idx,以便于分配新的节点编号。

        然后,我们实现两个函数:insert(),向集合中插入一个字符串和query(),询问一个字符串在集合中出现了多少次。

        insert()函数的实现很简单:遍历字符串,若当前字符不存在,我们就新建一个节点并分配编号,直到遍历结束,我们在字符串末尾打上标记。

        query()函数的实现和insert()函数大体相同:遍历字符串,若当前字符不存在,就直接退出寻找,返回0,最后若没有退出寻找,返回所对应的标记的出现次数。

        Trie树的结构非常好懂,实际上,它的节点中不仅能存储字符,还可以存储数字和一些别的东西,在下一篇文章中,Trie树则存储了二进制数字,具体内容请期待下周周六我所发的文章。

代码

        下面给出Trie树之字符串统计问题的实现代码:

int son[N][26],cnt[N],idx;

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];
}

上一篇-KMP算法的实现    C++算法基础专栏文章    下一篇-Trie树之最大异或对问题


每周六更新一篇文章,内容一般是自己总结的经验或是在其他网站上整理的优质内容

点个赞,关注一下呗~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值