题目描述
维护一个字符串集合,支持两种操作:
- I x 向集合中插入一个字符串 x;
- Q x 询问一个字符串在集合中出现了多少次。
共有 N (1≤N≤2×10^4) 个操作,输入的字符串总长度不超过 10^5,字符串仅包含小写英文字母。
输入格式
第一行包含整数 N,表示操作数。
接下来 N 行,每行包含一个操作指令,指令为 I x 或 Q x 中的一种。
输出格式
对于每个询问指令 Q x,都要输出一个整数作为结果,表示 x 在集合中出现的次数。
每个结果占一行。
输入样例
5
I abc
Q abc
Q ab
I ab
Q ab
输出样例
1
0
1
注释版代码
//题目链接:http://47.110.135.197/problem.php?id=5994
#include<iostream>
using namespace std;
const int N=100010;
char str[N];//表示输入的字符串
int idx,son[N][26],cnt[N];
//idx表示创建的每一个新节点唯一标识,因此需要自增
//当son为空值时,我们需要创建新节点,随后将idx赋给他,表明他的唯一标识,有了idx他就不为0了,就说明有值了
//那为什么idx不能设为一个固定值呢,因为后期查询的时候需要把son的值传给p,这里需要区分开
//而且最后一个字符的idx还需要作为p这个节点给统计单词数量
//son[][26]是为了存放每个节点的子节点,二维数组开26是因为只有26个英语字母
//cnt[]表示以每个节点结尾的单词数量
void insert(char str[])
{
int p=0;//将根节点定义为0
for(int i=0;str[i];i++)
{
int u=str[i]-'a';//将输入的26个英文字母转化为0-25的数字
if(!son[p][u]) son[p][u]=++idx;//如果当前根节点没有u这个子节点,那么创建子节点,并给他唯一的标识
p=son[p][u];//然后遍历下一个节点,“有路走路,没路建路”
}
cnt[p]++;//最后给以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;
cin>>n;
char op;
for(int i=0;i<n;i++)
{
cin>>op;
if(op=='I') cin>>str,insert(str);
else if(op=='Q') cin>>str,cout<<query(str)<<endl;
}
return 0;
}
标签:26,idx,Trie,son,int,str,节点,字典
From: https://blog.csdn.net/r2931887650/article/details/142458503