29.Acwing基础课第835题-简单-Trie字符串统计
29.Acwing基础课第835题-简单-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
代码:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<cstdio>
#include<string>
using namespace std;
const int N = 100010;
//idx相当于一个分配器,如果需要加入新的结点就用++idx分配出一个下标
//cnt[x]表示以x号结尾的单词多少个
//idx是有值的节点的个数
int son[N][26], cnt[N], idx;//下标是0的点,既是根节点,又是空节点
char str[N];
void insert(char str[])
{
//每次都从第一个结点开始遍历
int p = 0;
for (int i = 0; str[i]; i++)
{
//用数字0~25代表a~z
int u = str[i] - 'a';
//判断这个结点是否存在这个字母,如果不存在的话,新创一个结点存储该字母
//p表示的是第几个结点,u表示的是哪个字母,如果son[p][u]不为空就证明有以这个字母为值的子结点
//它代表的值就是指向了该子结点,即说明了第几个结点是它的子结点
//如son[2][1]=3,表示结点2有一个值为b(第二个数字代表的是a~z)的子结点,是结点3
if (!son[p][u]) son[p][u] = ++idx;
//令son[p][u]设置为父结点
p = son[p][u];
}
//以这个节点为末尾的字符串个数加1
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);
while (n--)
{
char op[2];
scanf("%s%s", op, str);
if (*op == 'I') insert(str);
else printf("%d\n", query(str));
}
return 0;
}
分析
简介:
Trie又称字典树,前缀树,是一种支持插入和查找字符串的多叉树,每个节点对应一个字符,节点编号各不相同,根节点为0,其它节点编号用于标识路径,边表示字符

使用trie用于维护字符串集合,支持两种操作
1:void insert(char[]) 向集合中插入一个字符串
2:int query(char[]) 查询集合中莫格字符串出现的次数
数据储存:
子节点数组:
int son[p][u]储存p号节点沿着u这条边走到的子节点编号
第二维储存边,边为26个小写字母a~z的映射为0~25,即每个节点至多有26个分叉
比如:
son[0][2]=1表示从0号节点(根节点)沿c边走到的节点是1号节点
son[1][0]=2表示从1号节点沿着a边走到的节点是2号节点
son[2][19]=3表示从2号节点沿着t边走到的节点是3号节点
计数数组:
int cnt[p]储存以p号节点为结尾的字符串插入次数(每个节点是唯一的)
cnt[3]=1表示以3号节点为结尾的字符串数量插入了1次(即”cat”插入1次)
节点编号:
int idx全局变量用于给节点进行编号,每插入一个节点,就++,根节点和空节点都为NULL
插入流程:
1.空树有且仅有一个根节点,编号为0
2.从根节点开始遍历,枚举待插入串的每个字符同时转换成映射值
如果有子节点(有路径),指针p走到子节点
如果没有(无路径),先使用idx创建新的子节点,指针p再走到子节点
3.在字符串最末字符代表的节点处更新次数
模拟一下:
向空树中先后插入
cat
car
busy
cate

查找:
1.从根节点开始遍历,扫描字符串
2.如果无字符s[i],结束查找并直接返回0
3.如果有字符s[i],继续扫描查找,直到词尾匹配,则返回cnt[p]

浙公网安备 33010602011771号