Trie树 模板

普通Trie:

struct TRIE{
    int trie[MAXN][2],tot,end[MAXN];
    TRIE(){tot=1;}
    void insert(char *s){//s为要插入的字符串 
        int len=strlen(s);
        int u=1;//1为根节点 
        for(int i=0;i<len;i++){
            int c=s[i]-'a';//'a'有时需换成'A'或'0' 
            if(!trie[u][c])//没有共同前缀,建立一个新的 
                trie[u][c]=++tot;//tot为总点数 
            u=trie[u][c];//继续向下插入单词 
        }
        end[u]=true;//标记是一个出现过的单词(图中涂红色) 
    }
    //查找单词是否是词典中某单词的前缀
    bool find1(char *s){//s为要查找的字符串 
        int len=strlen(s);
        int u=1;//1为根节点 
        for(int i=0;i<len;i++){
            int c=s[i]-'a';//'a'有时需换成'A'或'0' 
            if(!trie[u][c])//单词没有出现,直接返回false 
                return false;
            u=trie[u][c];//继续向下查找单词 
        }
        //如果扫描完了这个单词 
        return true;//是某个单词的前缀 
    }
    //查找单词是否在词典中出现过
    bool find2(char *s){//s为要查找的字符串 
        int len=strlen(s);
        int u=1;//1为根节点 
        for(int i=0;i<len;i++){
            int c=s[i]-'a';//'a'有时需换成'A'或'0' 
            if(!trie[u][c])//单词没有出现,直接返回false 
                return false;
            u=trie[u][c];//继续向下查找单词 
        }
        //如果扫描完了这个单词 
        return end[u];//如果出现过,返回true;如果没有出现过(是前缀),返回false 
    }
}Trie;

01Trie:

struct TRIE_01{
    int trie[MAXN*32][2],tot,end[MAXN*32];
    TRIE_01(){tot=1;}
    void insert(int x){
        int root=1;
        for(int i=32;i>=0;i--){
            int t=((x>>i)&1);
            if(!trie[root][t]) trie[root][t]=++tot;
            root=trie[root][t];
        }
		end[root]=x;
    }
	int query(int x){ //查询所有数中和 x异或结果最大的数 
		int root=1;
		for(int i=32;i>=0;i--){
		    int v=(x>>i)&1;
		    //利用贪心策略,优先寻找和当前位不同的数 
		    if(trie[root][v^1]) root=trie[root][v^1];
		    else root=trie[root][v];
		}
		return end[root]; //返回结果 
	}
}Trie_01;

它还可以有平衡树的作用:

题目就是普通平衡树

#include <cstdio>
#include <algorithm>
#include <cstring>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 100010 * 33 
using namespace std;
int root=1,tot=1,sumv[maxn],n,opt,x,ch[maxn][2]; 
void ins(int val,int c){
    val += (int)1e7;
    for(int i=31,p=root,t;i>=0;--i){
        t=(val>>i)&1;
        if(!ch[p][t]) ch[p][t]=++tot;
        p=ch[p][t]; sumv[p]+=c; 
    }
}
int rank(int val){
    val += (int)1e7; 
    int res=0,p=root; 
    for(int i=31;i>=0;--i){
        int t=(val>>i)&1;
        if(t) res += sumv[ch[p][0]];
        p=ch[p][t]; 
    }
    return res; struct TRIE_01{
    int trie[MAXN*32][2],tot,end[MAXN*32];
    TRIE_01(){tot=1;}
    void insert(int x){
        int root=1;
        for(int i=32;i>=0;i--){
            int t=((x>>i)&1);
            if(!trie[root][t]) trie[root][t]=++tot;
            root=trie[root][t];
        }
		end[root]=x;
    }
	int query(int x){ //查询所有数中和 x异或结果最大的数 
		int root=1;
		for(int i=32;i>=0;i--){
		    int v=(x>>i)&1;
		    //利用贪心策略,优先寻找和当前位不同的数 
		    if(trie[root][v^1]) root=trie[root][v^1];
		    else root=trie[root][v];
		}
		return end[root]; //返回结果 
	}
}Trie_01;

}
int kth(int val){
    int k=root,res=0;
    for(int i=31;i>=0;--i){
        if(val>sumv[ch[k][0]]) res|=(1<<i),val-=sumv[ch[k][0]],k=ch[k][1];
        else k=ch[k][0]; 
    } 
    res-=(1e7); return res; 
}
int main(){
    //setIO("input");
    scanf("%d",&n);
    while(n--){
        scanf("%d%d",&opt,&x);
        if(opt==1) ins(x,1);
        else if(opt==2) ins(x,-1);
        else if(opt==3) printf("%d\n",rank(x)+1);
        else if(opt==4) printf("%d\n",kth(x));
        else if(opt==5) printf("%d\n",kth(rank(x)));
        else if(opt==6) printf("%d\n",kth(rank(x+1)+1)); 
    }
    return 0; 
}

 

posted @ 2019-08-02 09:55  xukl21  阅读(154)  评论(0编辑  收藏  举报