1、"Trie树" 作用:
- 高效地存储和查找字符串集合的数据结构。
2、"Trie树" 存储字符串的形式如下:
(1)、用 "0" 来表示 "根节点(root)"。
(2)、存入一个字符串时,会在字符串最后结尾的那个字符节点打上标记。比如:字符串 "abcd" 是以字符 "d" 结尾的,那么就在字符节点 "d" 打上标记。
3、"Trie树" 查找过程:
(1)、假设查找字符串 "acbd",从 "根节点(root)" 出发,来到第一个字符 "a","a" 存在;来到第二个字符 "c","c" 存在;来到第三个字符 "b","b" 存在;来到第一个字符 "d","d" 存在;并且字符 "d" 有标记,表示存在一个字符串以 "d" 结尾,则该字符串存在。
(2)、假设查找字符串 "ab",从 "根节点(root)" 出发,来到第一个字符 "a","a" 存在;来到第二个字符 "b","b" 存在;但是字符 "b" 没有标记,说明没有字符串以 "b" 结尾,则该字符串不存在。
(3)、假设查找字符串 "ace",从 "根节点(root)" 出发,来到第一个字符 "a","a" 存在;来到第二个字符 "c","c" 存在;来到第三个字符 "e","e" 不存在;则说明该字符串不存在。
4、题目描述——摘录AcWing
输入样例:
5
I abc
Q abc
Q ab
I ab
Q ab
输出样例:
1
0
1
5、关于此题的具体分析:
举例:"son[0] [1]" 含义就是0号爸爸有个儿子 "b" ,那son[0] [1] = 2,就是0号爸爸有个儿子 "b",儿子的下标是 "2"; 下标是由 "idx" 来赋值的。(此处的下标可以形象地理解为该儿子的身份证id)
①、"son[0] [0]" 表示为0号爸爸(根节点root)有个孩子为 "a",孩子 "a" 的下标为 "1"。
②、"son[1] [1]" 表示为1号爸爸("a")有个孩子为 "b",孩子 "b" 的下标为 "2"。
③、"son[2] [2]" 表示为2号爸爸("b")有个孩子为 "c",孩子 "c" 的下标为 "3"。
④、"son[3] [3]" 表示为3号爸爸("c")有个孩子为 "d",孩子 "d" 的下标为 "4"。
⑤、"son[3] [4]" 表示为3号爸爸("c")有个孩子为 "e",孩子 "e" 的下标为 "5"。
⑥、"son[1] [2]" 表示为1号爸爸("a")有个孩子为 "c",孩子 "c" 的下标为 "6"。
⑦、"son[6] [1]" 表示为6号爸爸("c")有个孩子为 "b",孩子 "b" 的下标为 "7"。
⑧、"son[7] [1]" 表示为7号爸爸("b")有个孩子为 "d",孩子 "d" 的下标为 "8"。
6、代码实现:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int son[N][26], cnt[N], idx; //因为题目说"字符串仅包含小写英文字母",所以每个节点最多有 "26个孩子"。
char str[N];
void insert(char str[])
{
int p = 0;
for (int i = 0; str[i]; i++) //字符串是以"\0"结尾,如果读到"\0"表示字符串已经读完。
{
int u = str[i] - 'a'; //son[p][u]中"p"表示当前节点字符(孩子)的爸爸的下标; "u"表示当前节点(孩子)的字符。
if (!son[p][u])
{
son[p][u] = ++idx; //生成当前节点(孩子)的下标(相当于生成当前节点的身份证id)
}
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]) //通过前面生成每个节点的身份证id,在查询字符串时,可以判断字符串中字符是否存在。
{
return 0; //如果不存在就直接返回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));
}
}
system("pause");
return 0;
}