[浅谈] 字典树

字典树

其实是将字母放在树边上,利用空间换时间,解决前缀等问题。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=3e6+110;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int T,n,q,t[N][65],rt,newpos,cnt[N];char s[N];
int tn(char sc){
	if(sc>='A' && sc<='Z')return sc-'A'+1;
	if(sc>='a' && sc<='z')return sc-'a'+1+26;
	if(sc>='0' && sc<='9')return sc-'0'+1+26+26;
	return 0;
}
void Clear(int u){
	for(int i=1;i<=26+26+10;i++){
		if(t[u][i]){
			Clear(t[u][i]);
			t[u][i]=0;
		}
	}
	return;
}
void solve(){
	for(int i=1;i<=newpos;i++)cnt[i]=0;Clear(rt);
	rt=newpos=1;
	n=read(),q=read();
	for(int i=1;i<=n;i++){
		scanf("%s",s);int len=strlen(s),np=rt;
		for(int j=0;j<len;j++){
			int w=tn(s[j]);
			if(t[np][w])np=t[np][w];
			else np=t[np][w]=++newpos;
			cnt[np]++;
		}
	}
	for(int i=1;i<=q;i++){
		scanf("%s",s);int len=strlen(s),np=rt,flag=1;
		for(int j=0;j<len;j++){
			int w=tn(s[j]);
			if(t[np][w])np=t[np][w];
			else{flag=0;break;}
		}
		if(flag)printf("%d\n",cnt[np]);
		else printf("0\n");
	}
	return;
}
int main(){
	T=read();
	while(T--)solve();
	return 0;
}

01Trie

\(0,1\) 放在树边上即可,因为二进制的高位特性,可以谈贪心地让高位为优,以此解决异或的一些问题。如:
P4551 最长异或路径

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+110,M=2e5+110;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int n,st[N],top,Rans;
int head[N],last[M],to[M],tot,w[M];
void Dadd(int u,int v,int t){
	to[++tot]=v,w[tot]=t,last[tot]=head[u],head[u]=tot;
	to[++tot]=u,w[tot]=t,last[tot]=head[v],head[v]=tot;
	return;
}
void dfs(int u,int val,int fa){
	st[++top]=val;
	for(int i=head[u];i;i=last[i]){
		int v=to[i];if(v==fa)continue;
		dfs(v,val^w[i],u);
	}
	return;
}
int t[N*20][2],rt,poscnt;
void add(int x){
	int np=rt;
	for(int i=30;i>=0;i--){
		bool v=(x&(1<<i));
		if(t[np][v])np=t[np][v];
		else np=t[np][v]=++poscnt;
	}
	return;
}
int query(int x){
	int np=rt,ans=0;
	for(int i=30;i>=0;i--){
		bool v=(x&(1<<i));
		if(t[np][!v]){
			ans+=(1<<i);
			np=t[np][!v];
		}
		else np=t[np][v];
	}
	return ans;
}
int main(){
	n=read();
	for(int i=1;i<n;i++){int u=read(),v=read(),t=read();Dadd(u,v,t);}
	dfs(1,0,0);
	rt=poscnt=1;
	for(int i=1;i<=top;i++){
		if(i!=1)Rans=max(Rans,query(st[i]));
		add(st[i]);
	}
	printf("%d\n",Rans);
	return 0;
}
posted @ 2023-07-17 20:12  FJOI  阅读(8)  评论(0)    收藏  举报