trie树:时间复杂度O(n),n是树的宽度
trie树用来存储和查找字符串的数据结构。
建树
输入一个字符,如果该字符之前没出现过,那么就顺着原路径建立新的节点来存储该字符,否则,另辟蹊径,重新开分支路径建立节点来存储字符。直达字符串全部建立完为止。
模板题
#include<iostream>
using namespace std;
const int N=100010;
int son[N][26];//每行代表一个节点,每列代表一个字符
int cnt[N];//存储以特定节点结尾的字符串的计数
int idx; ////表示当前要插入的节点是第几个,每创建一个节点值+1
char str[N];
//插入
void insert(char str[])
{
int p=0;//根节点,为0
for(int i=0;str[i];i++)
{
int u=str[i]-'a'; //给26个字母建立映射,从0到26
if(!son[p][u])son[p][u]=++idx; //如果p节点不存在u这个儿子,那么就创建u这个儿子
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])return 0;//节点不存在就查不到
p=son[p][u];//挪动指针
}
return cnt[p];//返回以p结尾的单词数量
}
int main()
{
int n;
scanf("%d",&n);//输入n行
while(n--)
{
char op[2];//op[0]存实际数据,op[1]存"/n"
scanf("%s%s",op,str);//先读入操作类型,再读入要操作的字符串
if(op[0]=='I')insert(str);//如果输入的操作数是I,那就进行插入
else printf("%d\n",query(str));//否则输入的就是Q,就把查询结果打印出来
}
return 0;
}