Trie

传说中的字典树,来学习一下

实现字符串快速检索的多叉树结构

基本操作过程

1.初始化

一个空Trie仅包含一个根节点,该点的字符指针为空

2.插入

当需要插入一个字符串S时,令一个指针P起初指向根节点,然后依次扫描S中的每个字符c

1)若P的c字符指针指向一个已经存在的节点Q,则令P=Q;

2)若P的c字符指针为空,则新建一个节点Q,令P的c字符指针指向Q,然后令P=Q;

当S中的字符扫描完毕,在当前节点P上标记它是一个字符串的末尾//?

3.检索

当需要检索一个字符串S在Trie中是否存在,我们令一个指针P起初指向根节点,然后依次扫描S中的每个字符c:

1)若P的c字符指针指向一个已经存在的节点Q,则令P=Q;

2)若P的c字符指针为空,说明S没有被插入过,结束检索;

当S的字符扫描完毕,若当前节点P被标记为一个字符串末尾,则说明S在Trie中存在。否则,不存在。

下给出插入检索代码:

int trie[SIZE][26],tot=1;//初始化,假设每个字符都是小写字母
void insert(char *str){//插入
          int len =strlen(str),p=1;
          for(int k=0;k<len;k++){
                int ch=str[k]-'a';
                if(trie[p][ch]==0)trie[p][ch]=++tot;//tot定位下一个字母位置
                p=trie[p][ch];
         }
         end[p]=true;
}
bool search(char *str)//检索
{
        int len=strlen(str),p=1;
        for(int k=0;k<len;k++){
            p=trie[p][str[k]-'a'];
            if(p==0)return false;
        }
        return end[p];
}

 前缀统计

#include<bits/stdc++.h>
using namespace std;
#define SIZE 1000010
int trie[SIZE][26];
int tot=1;
int ed[SIZE];
int ans=0;
void insert(char *s)
{
    int len=strlen(s);
    int p=1;
    for(int i=0;i<len;i++){
        if(trie[p][s[i]-'a']==0){
            trie[p][s[i]-'a']=++tot;
        }
        p=trie[p][s[i]-'a'];
        
    }
    ed[p]++;
}
void search(char *s)
{
    int len=strlen(s);
    int p=1;
    for(int i=0;i<len;i++){
        if(trie[p][s[i]-'a']==0){
            return;
        }
        p=trie[p][s[i]-'a'];
        ans+=ed[p];  
    }
    //ans+=end[p];
    
}
char s[1000010];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%s",s);
        insert(s);
    }
    for(int i=0;i<m;i++){
         scanf("%s",s);
        ans=0;
        search(s);
        
        cout<<ans<<'\n';
    }
    
}

  最大异或对

沿与Ai当前位置相反的字符指针向下访问

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll A[100005];
ll ed[4200005];
int B[4200005][2];
int tot=1;
int F[32];
void div(ll x)
{
    int i=0;
    while(x){
        if(x&1){
            F[i]=1;
        }
        else F[i]=0;
        x>>=1;
        i++;
    }
    while(i<32){
        F[i]=0;
        i++;
    }
    
}
void insert(ll x)
{
    int p=1;
    div(x);
    for(int i=0;i<32;i++){
       if(!B[p][F[31-i]]){
           B[p][F[31-i]]=++tot;
       }
       
       p=B[p][F[31-i]];
    }
    ed[p]=x;
}
ll search(ll x)
{
    int p=1;
    div(x);
    for(int i=0;i<32;i++){
        if(B[p][!F[31-i]]){
            p=B[p][!F[31-i]];
        }
        else p=B[p][F[31-i]];
       
    }
    return x^ed[p];
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lld",&A[i]);
        insert(A[i]);
    }
    ll ans;
    for(int i=0;i<n;i++){
        if(i==0)ans=search(A[0]);
        else
        ans=max(ans,search(A[i]));
    }
    cout<<ans<<'\n';
    
}

 

 

 

posted @ 2019-07-23 11:53  liulex  阅读(306)  评论(0)    收藏  举报