Trie树字符串匹配
Trie树实际上是一个多叉树的结构,实用于字符串的匹配。
Trie树中有个二维数组 son[N][26],表示当前结点的儿子,如果没有的话,可以等于++idx。Trie树本质上是一颗多叉树,对于字母而言最多有26个子结点。所以这个数组包含了两条信息。比如:son[1][0]=2表示1结点的一个值为a的子结点为结点2;如果son[1][0] = 0,则意味着没有值为a子结点。
维护一个字符串集合,支持两种操作:
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
//son表示的是当前节点的的儿子节点
//tag表示的是叶子结点被用到的次数
//idx表示当前节点号
int son[N][26], tag[N], idx;
char str[N];
void insert(char str[])
{
int p = 0; //从根结点开始遍历
//读入最后会有一个\0作为字符串的结束标志符
for(int i = 0; str[i]; i ++)
{
int x = str[i] - 'a';
if(son[p][x] == 0) son[p][x] = ++ idx; //没有该子结点就创建一个
p = son[p][x]; //走到p的子结点
}
tag[p] ++;
}
int query(char str[])
{
int p = 0;
for(int i = 0; str[i]; i ++)
{
int x = str[i] - 'a';
if(son[p][x] == 0) return 0;
p = son[p][x];
}
return tag[p];
}
int main()
{
int n;
cin >> n;
while(n --)
{
char op[2];
//有好多测试点会输一些空格啊啥的,用字符串可以有效避免这些无效字符,所以即使用字符,也用数组存好一点
scanf("%s%s", op, str);
if(*op == 'I') insert(str); //*op打印op[0] ; op打印整个数组
else if(*op == 'Q') cout << query(str) << endl;
}
return 0;
}