Trie树练习
T1
一道字典树的模板。
字典树(又称Trie树)是一个树形结构,可以快速插入
、删除字符串以及匹配前缀。
简单地说,就是有一个多叉树,每个结点都有自己的编号,每条有父结点连接到子结点的边上都有一个字符。
若要插入字符串,则从根结点开始遍历每一条边。若有符合的字符,则沿这条边继续往下遍历,处理字符串的下一位;否则,为这个结点添加一个子节点,编号为当前树中最大编号+1,再沿这条边继续往下遍历,处理字符串的下一位。记得要将前缀数组中的值+1。
若要查找字符串,也从根结点开始遍历每一条边。若有符合的字符,则沿这条边继续往下遍历,处理字符串的下一位;否则,直接判为查找失败。
如果最后找到了整个字符串(即使没有遍历到树叶),则返回这个结点在前缀数组中的值(再遍历太费时间了,这就是字典树的优势)。
若要删除字符串,还是根结点开始遍历每一条边。若有符合的字符,则将当前结点前缀数组的值减去这个字符串的前缀数组的值(这是为了预防在下次查找中错误的被查找到),若前缀数组的值
详见Code:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int n;
string s1,s2;
int trie[400001][26];
int tot, sum[400001];
char s[31];
void ist(){
int ls=strlen(s);
int root=0;
for(int i=0;i<ls;i++){
int id=s[i]-'a';
if(!trie[root][id]){
++tot;
trie[root][id]=tot;
}
++sum[trie[root][id]];
root=trie[root][id];
}
return;
}
int src(){
int root=0;
int ls=strlen(s);
for(int i=0;i<ls;i++){
int id=s[i]-'a';
if(!trie[root][id]) return 0;
root=trie[root][id];
}
return sum[root];
}
void del(){
int ls=strlen(s),k=src();
int root=0;
for(int i=0;i<ls;i++){
int id=s[i]-'a';
sum[trie[root][id]]-=k;
if(sum[trie[root][id]]<=0) trie[root][id]=0;
root=trie[root][id];
}
return;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>s1>>s;
if(s1=="insert"){
ist();
}else if(s1=="delete"){
del();
}else{
if(src()) cout<<"Yes\n";
else cout<<"No\n";
}
}
return 0;
}