一、链接
835. Trie字符串统计
二、题目
维护一个字符串集合,支持两种操作:
I x
向集合中插入一个字符串 xx;Q x
询问一个字符串在集合中出现了多少次。
共有 NN 个操作,所有输入的字符串总长度不超过 105105,字符串仅包含小写英文字母。
输入格式
第一行包含整数 NN,表示操作数。
接下来 NN 行,每行包含一个操作指令,指令为 I x
或 Q x
中的一种。
输出格式
对于每个询问指令 Q x
,都要输出一个整数作为结果,表示 xx 在集合中出现的次数。
每个结果占一行。
数据范围
1≤N≤2∗1041≤N≤2∗104
输入样例:
5
I abc
Q abc
Q ab
I ab
Q ab
输出样例:
1
0
1
三、题意
利用Trie来存储和查询字符串,属于模板题
四、代码
#include<iostream>
using namespace std;
const int N=1e5+10;
char str[N];
int son[N][26],idx,cnt[N];
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];
}
int main()
{
int n;
scanf("%d",&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;
}
五、总结
1.类似于使用字典来进行查询
2.构建Trie来存储和查询字符串,把字符串分解成为一个一个的字符(遍历字符串来实现),给每一个结点一个特定的编号,遍历字符串结束之后,用一个计数器数组来计数或者说标记,把那个特定的编号作为下标(idx),对应的计数器数值增加一,表示字符串结束了
3.存储函数:定义一个p,表示节点,初始值为0,定义一个u,把小写英文字母映射成为0-25数字存在u里面,如果结点是空的,就新建立一个节点,其实是给这个二维数组元素一个特定的编号, 用p来存储这个结点,编号是从1开始增加使用的,也就是说,最小的使用的编号是1。
4.存储函数里面,循环里面有一个步骤,把son[p][u]赋值给p,表示有这个结点,可以继续下一个结点
5.查询函数和存储函数类似:有一个细节说明一下,把英文映射成为数字,减去小写字母a,就可以让a->0,b->1,...,z->25,只要中间有一个结点没有查询出来,就表示没有这个字符串,返回0即可,最后循环结束,返回计数器里面的数值即可
6.输入输出并不复杂
7.学习这个题就感觉非常轻松,kmp是真的难
8.计数器那里说明一下,用下标表示结点,数组元素表示出现的次数,非常巧妙,感觉用pair或者二维数组或者结构体也可以,用数组下标和数组元素数值应该是最简便的
9.遍历的时候,str[]最后一个元素是\0,所以会跳出循环,比较简便