字典树
字典树用于记录字符串是否出现过,某前缀出现过几次,操作有建树、添加、查找、删除
#include<bits/stdc++.h>
using namespace std;
const int N=3e6+10;
int tree[N][70],element[N],idx=0;//element记录是否末尾/前缀的累加,建树
void add_tree(string a);
int search_tree(string a);
int mark(char x);
//删除操作可以字符串先查找操作,再从后往前逆向地切断链表,还原element
int T,n,q;
int main()
{
string a;
cin>>T;
while(T--)
{
cin>>n>>q;
for(int i=0;i<n;i++)
{
cin>>a;
add_tree(a);
}
for(int i=0;i<q;i++)
{
cin>>a;
cout<<search_tree(a)<<endl;
}
for(int i=0;i<=idx;i++)
{
memset(tree[i],0,sizeof(tree[i]));
}
memset(element,0,sizeof(int)*(idx+1));
idx=0;
}
return 0;
}
void add_tree(string a)//插入
{
int p=0;
for(int i=0;i<a.length();i++)
{
if(tree[p][mark(a[i])]==0)
{
tree[p][mark(a[i])]=++idx;
p=tree[p][mark(a[i])];
element[p]++;
}
else
{
p=tree[p][mark(a[i])];
element[p]++;
}
}
}
int search_tree(string a)//查找
{
int p=0;
for(int i=0;i<a.length();i++)
{
if(tree[p][mark(a[i])]==0)
{
return 0;
}
else p=tree[p][mark(a[i])];
}
return element[p];
}
int mark(char x){//映射
if(x>='A'&&x<='Z')
return x-'A';
else if(x>='a'&&x<='z')
return x-'a'+26;
else
return x-'0'+52;
}