字典树模板题。涉及到字典树的插入,查询,删除操作。
最开始使用的是动态数组来解,这样做的话,如果测试样例先是删除操作,就会报数组溢出错误。奉上字典树模板
开始使用这个模板时,说这个模板容易爆内存溢出,不过多虑了(大概开350万才会爆),除此之外时间也稍微久了一点,但是理解相比其它字典树模板也更加容易
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1000005;
const int maxm=27;
struct Trie{
int ch[maxn][maxm];
int cnt[maxn];
int num;
void init(){
memset(ch[0],0,sizeof(ch[0]));
memset(cnt,0,sizeof(cnt));
num=0;
}
int newnode(){
num++;
memset(ch[num],0,sizeof(ch[num]));
cnt[num]=0;
return num;
}
void insert(char*s){ //插入操作,u控制树的深度
int u=0;
for(int i=0;s[i];i++){
if(!ch[u][s[i]-'a']) //如果该点没有被访问 ,那么就初始化该点
ch[u][s[i]-'a']=newnode();//初始化之后,除了该点的值为num,其它点都为0
u=ch[u][s[i]-'a'];
cnt[u]++; //记录有多少点经过此处,如果刚开始学字典树,有点不懂的话,建议大家可以用一组测试数据看下结果
//cout<<cnt[u]<<endl; // 试着查看一下cnt数组的变化,可以加深理解
}
}
int find(char *s) //查询操作
{
int u=0;
for(int i=0;s[i];i++) //一直执行,直到s字符串中的字符在字典树中不存在或者执行完毕
{
if(!ch[u][s[i]-'a']) //如果该点的值为0,那么字典树就没有这个字符串。
return 0;
u=ch[u][s[i]-'a'];
}
return cnt[u]; //如果存在,那么返回有多少点经过此处,在删除操作中可用
}
void del(char *s,int len){ //删除操作
int n=strlen(s),u=0;
if(len<=0)
return; //需要判断一下,可能没有这个前缀,删不了,没有这一步会报RE
for(int i=0;i<n;i++){
if(!ch[u][s[i]-'a'])
return;
cnt[u]-=len;
u=ch[u][s[i]-'a'];
}
cnt[u]=0;
for(int i=0;i<26;i++){
ch[u][i]=0;
}
}
}trie;
int main()
{
int n;
cin>>n;
trie.init();
while(n--)
{
char str1[40],str2[40];
cin>>str1>>str2;
if(str1[0]=='i')
trie.insert(str2);
else if(str1[0]=='s'){
if(trie.find(str2))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
else{
trie.del(str2,trie.find(str2));
}
}
return 0;
}
如果有问题,欢迎提出,再附上一个模板,但是这道题不能使用,动态开数组,有兴趣小伙伴可以捣鼓一下。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=1000005;
const int maxm=27;
struct Trie{
int *ch[maxn];
int cnt[maxn];
int tot;
void init(){
memset(ch,0,sizeof(ch));
memset(cnt,0,sizeof(cnt));
tot=0;
}
void insert(char *s){
int p=0;
for(int i=0;s[i];i++)
{
if(ch[p]==NULL){
ch[p]=new int[maxm];
memset(ch[p],-1,sizeof(int)*maxm);
}
if(ch[p][s[i]-'a']==-1){
ch[p][s[i]-'a']=++tot;
}
p=ch[p][s[i]-'a'];
cnt[p]++;
}
}
int find(char *s){
int p=0;
for(int i=0;s[i];i++){
if(ch[p][s[i]-'a']==-1){
return 0;
}
p=ch[p][s[i]-'a'];
}
return cnt[p];
}
void del(char *s,int len)
{
int n=strlen(s),p=0;
if(len<=0){
return;
}
for(int i=0;i<n;i++){
if(ch[p][s[i]-'a']==-1)
return;
cnt[p]-=len;
p=ch[p][s[i]-'a'];
}
cnt[p]=0;
for(int i=0;i<26;i++){
ch[p][i]=-1;
}
}
}trie;
int main()
{
int n;
cin>>n;
trie.init();
while(n--)
{
char str1[40],str2[40];
cin>>str1>>str2;
if(str1[0]=='i')
trie.insert(str2);
else if(str1[0]=='s'){
if(trie.find(str2))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
else{
trie.del(str2,trie.find(str2));
}
}
return 0;
}