字典树总结

字典树总结

字典树就是这样一个树。典型应用是用于统计和排序大量的字符串前缀来减少查询时。

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();
	}
}
posted @ 2025-06-07 10:39  MistyPost  阅读(17)  评论(0)    收藏  举报