【Trie树】

【Trie树/字典树/前缀树】

模版代码

【基础封装】

//注意使用时不要把空间开到栈里:开到全局变量 否则会RE
//若多组测试用例:记得trie.Clear()
struct Trie{
    int ch[N][70],cnt[N],idx=0;
    map<char,int> mp;
    Trie(){
        i64 id=0;
        for(char c='a';c<='z';c++) mp[c]=++id;
        for(char c='A';c<='Z';c++) mp[c]=++id;
        for(char c='0';c<='9';c++) mp[c]=++id;
    }
    void insert(string s){
        int u=0;
        for(int i=0;i<s.size();i++){
            int v=mp[s[i]];
            if(!ch[u][v]) ch[u][v]=++idx;
            u=ch[u][v];
            cnt[u]++; //放里面是前缀树
        }
        //cnt[u]++; //放外面是字典树
    }
    i64 query(string s){
        int u=0;
        for(int i=0;i<s.size();i++){
            int v=mp[s[i]];
            if(!ch[u][v]) return 0;
            u=ch[u][v];
        }
        return cnt[u];
    }
    void Clear(){
        for(int i=0;i<=idx;i++){
            cnt[i]=0;
            for(int j=0;j<=62;j++){
                ch[i][j]=0;
            }
        }
        idx=0;
    }
}trie;

【01字典树】

struct Trie{
    int n,idx;
    vector<vector<int>> ch;
    void init(int n){
        this->n=n;
        idx=0;
        ch.resize(64*(n+1),vector<int>(2));
    }
    void insert(int x){
        int u=0;
        for(int i=63;~i;i--){
            int &v=ch[u][(x>>i)&1LL];
            if(!v) v=++idx;
            u=v;
        }
    }
    int query(int x){
        int u=0;
        i64 res=0;
        for(int i=63;~i;i--){
            int v=(x>>i)&1LL;
            if(ch[u][!v]){
                res+=(1LL<<i);
                u=ch[u][!v];
            }
            else{
                u=ch[u][v];
            }
        }
        return res;
    }
}trie;

【模版题】
https://www.luogu.com.cn/problem/P8306
https://www.luogu.com.cn/problem/P10471

Trie树 字符串【模版】

题目来源:https://www.acwing.com/problem/content/837/

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n;
     //记录儿子
int son[N][26],cnt[N],idx=0;
char str[N];
void insert(char a[]){
	int p=0;
	for(int i=0;str[i];i++){
		int u=str[i]-'a';
		if(!son[p][u]) son[p][u]=++idx;//没有节点才插入节点 
		p=son[p][u];
	}
	cnt[p]++;
}
int query(char a[]){
	int p=0;
	for(int i=0;str[i];i++){
		int u=str[i]-'a';
		if(!son[p][u]) return 0;
		p=son[p][u];//往下找
	}
	return cnt[p];
}
int main(){
	cin>>n;
	while(n--){
		char a[2];
		scanf("%s%s",a,str);
		if(a[0]=='I') insert(str);
		else if(a[0]=='Q') cout<<query(str)<<'\n';
	}
	return 0;
}

最大异或对【Trie树应用】

题目来源:https://www.acwing.com/problem/content/145/

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
const int M=32*N;//一个数最多32位
int n;
int a[N];
int son[M][2],idx=0;
void insert(int x){
    int p=0;
    for(int i=30;i>=0;i--){
        int u=x>>i&1;
        if(!son[p][u]) son[p][u]=++idx;
        p=son[p][u];
    }
}
int query(int x){
    int p=0,res=0;
    for(int i=30;i>=0;i--){
        int u=x>>i&1;
        if(son[p][!u]){
            p=son[p][!u];
            res=res*2+1;//异或成功 +1
        }
        else{
            p=son[p][u];
            res=res*2+0;//异或不成功
        }
    }
    return res;
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        insert(a[i]);
    }
    int res=0;
    for(int i=0;i<n;i++){
        int t=query(a[i]);
        res=max(res,t);
    }
    printf("%d",res);
    return 0;
}
posted @ 2024-10-27 16:59  White_ink  阅读(10)  评论(0)    收藏  举报