字典树的作用:高效的存储和查找字符串
参考acwing.835 题解
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
char str[N]; //将要插入或查询的字符串
//son[N][26]用来存储Trie树的数据,子节点的位置,cnt[]存储每个单词的出现的次数
// idx相当于开辟插入的每个字母的空间,表示当前插入的结点是第几个,每开辟一个就+1
int son[N][26], cnt[N], idx;
//插入字符串
void insert(char str[])
{
int p = 0; //p类似于一个指针,指向当前的位置
for(int i = 0; str[i]; ++i)
{
int u = str[i] - 'a'; //将a~z映射到0~25
//如果遍历到的该字母未出现过,开辟新空间存储该字母
if(son[p][u] == 0) son[p][u] = ++ idx;
//如果该字母存在,更新指针p让p指向当前结点
p = son[p][u];
}
cnt[p] ++; //每插入一次字符串,用cnt[p]将该单词出现的次数+1
}
//查询字符串出现的次数
int query(char str[])
{
int p = 0;
for(int i = 0; str[i]; ++i)
{
int u = str[i] - 'a';
//若是son[p][u]为0,说明该字典树上(可能是一条分支)没有该结点,说明不存在该字符串
if(son[p][u] == 0) return 0;
//相等说明树上有该字母,继续向下查询
p = son[p][u];
}
//若是循环完都没return,说明存在该字符串,返回插入时所记录的插入的次数即可
return cnt[p];
}
int main()
{
int n;
cin >> n;
char op[2];
while(n--)
{
scanf("%s%s", op, str);
if(op[0] == 'I') insert(str);
else cout << query(str) << endl;
}
return 0;
}