字典树总结
字典树总结

字典树就是这样一个树。典型应用是用于统计和排序大量的字符串前缀来减少查询时。
1.根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3.每个节点的所有子节点包含的字符都不相同。
定义一个数组来模拟这个树:
\(p[i][j]\) 表示以i为父亲,j为儿子的点的编号。
如果在插入时发现没有值,插进去就好。
这个数据结构还能解决一些跟二进制有关的问题。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll t,n,q,cnt;
ll p[3000005][70],sum[5000000];
char s[1000000],ss;
ll che(char sp){
if(sp>='A'&&sp<='Z'){
return sp-'A'+1;
}
if(sp>='a'&&sp<='z'){
return sp-'a'+28;
}
if(sp>='0'&&sp<='9'){
return sp-'0'+2+54;
}
}
void gx(){
ll wz=0;
ll len=strlen(s);
for(int i=0;i<len;i++){
ll ls=che(s[i]);
if(!p[wz][ls]){
p[wz][ls]=++cnt;
}
wz=p[wz][ls];
sum[wz]++;
}
}
ll find(){
ll wz=0;
ll len=strlen(s);
for(int i=0;i<len;i++){
ll ls=che(s[i]);
if(!p[wz][ls]){
return 0;
}
wz=p[wz][ls];
}
return sum[wz];
}
void doo(){
for(int i=0;i<=cnt;i++){
for(int j=0;j<70;j++){
p[i][j]=0;
}
}
for(int i=0;i<=cnt;i++){
sum[i]=0;
}
cnt=0;
cin>>n>>q;
while(n--){
cin>>s;
gx();
}
while(q--){
cin>>s;
cout<<find()<<"\n";
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0) , cout.tie(0);
cin>>t;
while(t--){
doo();
}
}
可以自由转载

浙公网安备 33010602011771号