835. Trie字符串统计

Posted 幽殇默

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了835. Trie字符串统计相关的知识,希望对你有一定的参考价值。

在这里插入图片描述
https://www.acwing.com/problem/content/description/837/

Trie的概念: 高效地存储和查找字符串集合的数据结构。

y神的模板:

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

首先要注意的一点就是: N代表的是输入的字符串总长度。

也就是说,这个Trie树的结点个数和是小于等于N的。
在这里插入图片描述
第二点 idx的含义:其实和单链表里的那个含义差不多,如下图我已经用绿笔标出了结点对应的idx的值
在这里插入图片描述
需要注意的一点就是我们的每一个点,对应的idx都是唯一的,这样我们再找儿子的过程中就不会有一对多的情形。

第三点son[N] [26] 的含义
很多小伙伴,不知道这个的含义是啥。其是只要带个案例模拟一边你就懂了。
例: son[0][u] 这个的含义就是根节点它的孩子u结点的下标,跟单链表里的next指针其实是一样的。
不过有区别的一点是我们的单链表它的孩子只有一个,是一条链子。
但是我们的Trie是后面可能有26个孩子(因为英文字母只有26个),即有26种路径可以选的单链表。
在这里插入图片描述
例: abc
在这里插入图片描述
其实只要把字符串的每条路径当成一个单链表,就十分的容易理解了。
最后cnt[p] 的含义
就是该字符串出现的次数。比如上图的: abc 这条字符串单链表已经到头了,那么我们就 cnt[p]++,
p代表的就是c字符所对应的idx,idx我已经说了它和一个字符是唯一对应的,这里的唯一对应不仅是字符对应的关系还有位置(即树的层数)。
因为第1层的" a " 和 第二层的 " a ” 是不同的。

#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+10;
int cnt[N],son[N][26],idx;
void add(string s)
{
	int p=0;
	for(int i=0;i<s.size();i++)
	{
		int u=s[i]-'a';
		if(!son[p][u]) son[p][u]=++idx;
		p=son[p][u];
	}
	cnt[p]++;
}
int query(string s)
{
	int p=0;
	for(int i=0;i<s.size();i++)
	{
		int u=s[i]-'a';
		if(!son[p][u]) return 0;
		p=son[p][u];
	}
	return cnt[p];
}
int main(void)
{
	int n; cin>>n;
	while(n--)
	{
		string op,s; cin>>op>>s;
		if(op=="I") add(s);
		else cout<<query(s)<<endl;
	}
	return 0;
} 

以上是关于835. Trie字符串统计的主要内容,如果未能解决你的问题,请参考以下文章

Acwing_835Trie字符串统计

trie(字典树) C++版本 Python版本

算法零基础KMPTrieAC自动机

8.Trie字符串统计 Trie树,也叫字典树

HDU 1251 统计难题 (字符串-Trie树)

一个简单的统计问题(解决方案:Trie树)