字典树

发布时间 2023-03-22 21:17:24作者: 天雷小兔

1.动态分配空间

const int N = 27;
struct trie{
	trie *Next[N];
	int flag;
	trie(){
		flag=1;
		memset(Next,NULL,sizeof(Next));
	}
}*root;
void insert(string s){
	int len=s.length();
	trie *p=root,*q;
	for(int i=0;i<len;i++){
		int id=s[i]-'a';
		if(p->Next[id]==NULL){
			q=new trie();
			p->Next[id]=q;
			p=p->Next[id];
		}else{
			p=p->Next[id];
			(p->flag)++;
		}
	}
}
int query(string s){
	int len=s.length();
	trie *p=root;
	for(int i=0;i<len;i++){
		int id=s[i]-'a';
		p=p->Next[id];
		if(p==NULL)return 0;
	}
	return p->flag;
}
void free(trie *t){
	if(t==NULL)return;
	for(int i=0;i<N;i++)if(t->Next[i])free(t->Next[i]);
	delete(t);
}

  

2.静态空间

例题:洛谷P2580

const int N = 1e6+255;
struct node{
	bool rep;
	int son[30];
	int num;
}t[N];
int cnt=1,n,m;
char s[105];
void insert(char *s){
	int now=0;
	for(int i=0;s[i];i++){
		int ch=s[i]-'a';
		if(t[now].son[ch]==0)t[now].son[ch]=cnt++;
		now=t[now].son[ch];
		t[now].num++;
	}
}
int find(char *s){
	int now=0;
	for(int i=0;s[i];i++){
		int ch=s[i]-'a';
		if(t[now].son[ch]==0)return 3;
		now=t[now].son[ch];
	}
	if(t[now].num==0)return 3;
	if(t[now].rep==0){
		t[now].rep=1;
		return 1;
	}
	return 2;
}

  

3.查询公共前缀的数量

void insert(char str[]){
	int len=strlen(str),rt=0;
	for(int i=0;i<len;i++){
		int cur=str[i]-'a';
		if(trie[rt][cur]==0) trie[rt][cur]=++tot;
		rt=trie[rt][cur];
		num[rt]++;
	}
}
int ask(char str[]){
	int len=strlen(str),rt=0;
	for(int i 0;i<len;i++){
		int cur=str[i]-'a';
		if(trie[rt][cur]==0) return 0 ;
		rt=trie[rt][cur];
	}
	return num[rt];
}

  

4.字符串排序(字典序)

void trie_sort(trie *root){
	if(!root)return;
	if(root->flag){
		cout<<root->s<<'\n';
		return;
	}
	for(int i=0;i<26;i++)trie_sort(root->Next[i]);
}

  

5.维护最长异或路径

例题:洛谷P4551

 

const int N = 2e6+255;
struct edge{
	int v,w,next;
}e[N];
struct trie{
	int s[5];
}t[N];
int head[N],cnt=-1,sum[N],tot,n;
void add(int u,int v,int w){
	e[++cnt].next=head[u];
	e[cnt].v=v;
	e[cnt].w=w;
	head[u]=cnt;
}
void dfs(int x,int fa){
	for(int i=head[x];~i;i=e[i].next){
		int v=e[i].v,w=e[i].w;
		if(v!=fa){
			sum[v]=sum[x]^w;
			dfs(v,x);
		}
	}
}
void build(int va,int x){
	for(int i=(1<<30);i;i>>=1){
		bool c=va&i;
		if(!t[x].s[c])t[x].s[c]=++tot;
		x=t[x].s[c];
	}
}
int find(int va,int x){
	int ans=0;
	for(int i=(1<<30);i;i>>=1){
		bool c=va&i;
		if(t[x].s[!c]){
			ans+=i;
			x=t[x].s[!c];
		}else{
			x=t[x].s[c];
		}
	}
	return ans;
}
int main(){
	memset(head,-1,sizeof(head));cnt=-1;
	cin>>n;
	for(int i=1,x,y,z;i<n;i++){
		cin>>x>>y>>z;
		add(x,y,z);
		add(y,x,z);
	}
	dfs(1,-1);
	for(int i=1;i<=n;i++)build(sum[i],0);
	int ans=0;
	for(int i=1;i<=n;i++)ans=max(ans,find(sum[i],0));
	cout<<ans;
	return 0;
}

  

6.维护异或和

const int N = 21;
struct trie{
	int ch[(N+1)*225][2],w[(N+1)*225],xorv[(N+1)*225],tot;
	int mknode(){
		++tot;
		ch[tot][1]=ch[tot][0]=w[tot]=xorv[tot]=0;
		return tot;
	}
	void maintain(int o){
		w[o]=xorv[o]=0;
		if(ch[o][0]){
			w[o]+=w[ch[o][0]];
			xorv[o]^=xorv[ch[o][0]]<<1;
		}
		if(ch[o][1]){
			w[o]+=w[ch[o][1]];
			xorv[o]^=(xorv[ch[o][1]]<<1)|(w[ch[o][1]]&1);
		}
		w[o]&=1;
	}
	void inserts(int &o,int x,int dp){
		if(!o)o=mknode();
		if(dp>N)return (void)(w[o]++);
		inserts(ch[o][x&1],x>>1,dp+1);
		maintain(o);
	}
	void erase(int o,int x,int dp){
		if(dp>20)return (void)(w[o]--);
		erase(ch[o][x&1],x>>1,dp+1);
		maintain(o);
	}
	void addall(int o){
		swap(ch[o][0],ch[o][1]);
		if(ch[o][0])addall(ch[o][0]);
		maintain(o);
	}
	int merge(int a,int b){
		if(!a)return b;
		if(!b)return a;
		w[a]+=w[b];
		xorv[a]^=xorv[b];
		ch[a][0]=merge(ch[a][0],ch[b][0]);
		ch[a][1]=merge(ch[a][1],ch[b][1]);
		return a;
	}
}t;