AcWing 835. Trie字符串统计(详细注释,而且op改成char读入)
原题链接
简单
作者:
现代修士o_O
,
2021-04-23 21:39:35
,
所有人可见
,
阅读 263
//Tire:高效地存储和查找字符串集合地数据结构
//三个变量 son[N][26], cnt[N], idx
//两个操作,insert(char str[]), query(char str[])
#include <iostream>
using namespace std;
const int N = 100010;
//son[N][26] 表示 最多有N个结点,从0到N - 1, 0 既代表根结点又代表空结点,每个结点最多有26个子节点(分支,因为题目表示字符串仅包含小写英文字母)
//cnt[i] 表示 以下标为i的结点为末尾的字符串的个数
//idx 永远指向最后生成的结点下标++idx,0已经被根结点用了,而且空结点也是0(初始化的时候为空了)
int son[N][26], cnt[N], idx;
//插入一个字符串,也是代表存储一个字符串
void insert(char str[])
{
int p = 0; // 从根结点开始
for (int i = 0; str[i]; i ++ ) // 字符串以\0结尾,而\0 的ascll 为 0;
{
int u = str[i] - 'a';// 0..25 映射 a-z
if (!son[p][u]) son[p][u] = ++ idx;//son[p][u] == 0 意味着空结点。代表没有这个字符,所以分配一个结点给它
p = son[p][u];//到下一个结点,不管上一步分配与否,只要没走到字符串末尾,就一直走下去。
}
// 走完意味着str[i] == 0 ,p指向最后一个结点 ,那么这个结点+1,这个字符串的个数加一
cnt[p] ++ ;
}
//查询一个字符串,从根结点走到最后结点p,返回其个数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; // 如果中道崩殂,意味着没有这个字符串,返回个数0
p = son[p][u]; // 走到着,意味着 上面的if没执行,存在下p到u的路线。就走到u这个结点
}
return cnt[p]; // 走到最后一个结点了,不管它之前有没有以这里为末尾插入结点,返回cnt[p] 也就是到这个结点的字符串的个数。
}
int main()
{
int n;
cin >> n;
while (n -- )
{
char op;
char str[N];
getchar();
scanf("%c %s",&op ,str); //如果要读入字符的话,要getchar(); 实在麻烦,还是读入字符串方便,不用考虑上面的读入!
// printf("%c %s\n", op, str);
// cin >> op >> str;
if ('I' == op)
{
insert(str);
}
else
{
printf("%d\n",query(str));
}
}
return 0;
}