【AcWing基础题】TriesTree
此算法用于快速存储以及快速查找字符串
流程图
代码
#include <iostream>
using namespace std;
const int N = 100010;
//题目给定的是小写的英文字母,每个节点最多向外连26个边
//son数组的第一维是:父节点对应的idx
int son[N][26];
//cnt 是以当前这个点结尾的单词有多少个,idx表示当前用到了哪个下标 idx初始化为0
// 下标是0的点,既是根节点,又是空节点
int cnt[N], idx;
char str[N];
//存储也就是插入操作
void insert(char str[])
{
int p = 0;
//遍历字符串
for (int i = 0; str[i]; i++)
{
// 把当前字母 对应的子节点编号 搞出来
//把字母a-z 映射成0~25
// 因为'a' 的ascii 对应的是97 ,任何一个小写字母- 97 就是对应的位置。
int u = str[i] - 'a';
// 如果p节点没有u这个儿子,就把他创建出来
if (son[p][u] == 0)
{
son[p][u] = ++idx;
}
//走到下一个节点
p = son[p][u];
}
// 表示以这个点结尾的单词数量多了一个
//为什么不担心重复呢? 因为每个单词所给定的ascii值是不一样的,那么累加起来的p值【son[][]就是一个值呀】
//也是不一样的。那么如果P值一样,说明字符串一致呀,那么肯定加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[0] == 'I')
{
insert(str);
}
else
{
printf("%d\n", query(str));
}
}
return 0;
}