度熊手上有一本神奇的字典,你可以在它里面做如下三个操作:
1、insert : 往神奇字典中插入一个单词
2、delete: 在神奇字典中删除所有前缀等于给定字符串的单词
3、search: 查询是否在神奇字典中有一个字符串的前缀等于给定的字符串
Input
这里仅有一组测试数据。第一行输入一个正整数N(1≤N≤100000)N(1≤N≤100000),代表度熊对于字典的操作次数,接下来NN行,每行包含两个字符串,中间中用空格隔开。第一个字符串代表了相关的操作(包括: insert, delete 或者 search)。第二个字符串代表了相关操作后指定的那个字符串,第二个字符串的长度不会超过30。第二个字符串仅由小写字母组成。
Output
对于每一个search 操作,如果在度熊的字典中存在给定的字符串为前缀的单词,则输出Yes 否则输出 No。
Sample Input
5 insert hello insert hehe search h delete he search hello
Sample Output
Yes No
#include<stdio.h>
#include<cstring>
#include<iostream>
const int maxn = 1e6 + 5;
using namespace std;
int trie[maxn][30];
int vis[maxn];
int tot;
int num[maxn];
int flag;
void build(string a){
int root = 0;
int len = a.size();
for(int i = 0; i < len; i++){
int id = a[i] - 'a';
if(!trie[root][id])
trie[root][id] = ++tot;
root = trie[root][id];
num[root]++;
}
}
void query(string a){
int root = 0;
int len = a.size();
for(int i = 0; i < len; i++){
int id = a[i] - 'a';
if(!trie[root][id]){
cout << "No" << endl;
return ;
}
root = trie[root][id];
}
if(num[root])
cout << "Yes" << endl;
else{
cout << "No" << endl;
}
}
void cqc(int rt){//递归清零
for(int i = 0; i <= 30; i++){
if(trie[rt][i] != 0){
cqc(trie[rt][i]);
trie[rt][i] = 0;
num[rt] = 0;
}
}
}
void clear(string a){
int root = 0;
int cnt = 0;
for (auto i : a){
int id = i - 'a' ;
if (!trie[root][id]) return ;
root = trie[root][id] ;
}
cnt += num[root] ;
root = 0 ;
for (auto i : a){
int id = i - 'a' ;
root = trie[root][id] ;
num[root] -= cnt ;
}
cqc(root);
}
void init(){
memset(trie, 0, sizeof(trie));
tot = 0;
memset(num, 0, sizeof(num));
memset(vis, 0, sizeof(vis));
flag = 0;
}
string s1;
string s2;
int main(){
ios::sync_with_stdio(0);
init();
int n;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> s1 >> s2;
if(s1 == "insert"){
build(s2);
}
if(s1 == "search"){
query(s2);
}
if(s1 == "delete"){
clear(s2);
}
}
return 0;
}