0x16Trie

Trie(字典树)是一种用于实现字符串快速检索的多叉树结构。每个节点都拥有若干字符指针,若在插入或检索字符串时扫描到一个字符c,就沿着当前节点的c字符指针,走向下一个节点,直至遇到标志字符串结束。

基本操作
初始化
创建根节点,该点字符指针指向空。
插入
初始化一个指向根节点的指针p,依次扫描字符串S的各个字符c
若p节点的c字符指针指向某节点Q,令p=Q
若p节点的c字符指针指向空,创建一个新节点Q,令p的c字符指针指向Q,p=Q
当字符串S扫描完毕,在当前p节点上标记其为一个字符串的末尾
检索
初始化一个指向根节点的指针p,依次扫描字符串S的各个字符c
若p节点的c字符指针指向空,则S不存在该树中,结束检索
若p节点的c字符指针指向某节点Q,令p=Q,当S中字符全部检索完成,且当前节点p被标记为一个字符串的末尾,则字符串S存在于该Trie,否则不存在。

int trie[N][26],cnt[N],idx;
// 0号点既是根节点,又是空节点
// trie[][]存储树中每个节点的子节点
// cnt[]存储以每个节点结尾的单词数量
void insert(char* str)//插入一个字符串
{
	int len=strlen(str),p=0;
	for(int i=0;i<len;++i)
	{
		int u=str[i]-'a';
		if(!trie[p][u]) trie[p][u]=++idx;
		p=trie[p][u];
	}cnt[p]++;
}
int query(char *str)// 查询字符串出现的次数
{
	int p=0,len=strlen(str);
	for(int i=0;i<len;++i)
	{
		int u=str[i]-'a';
		if(!trie[p][u]) return 0;
		p=trie[p][u];
	}
	return cnt[p];
}

143. 最大异或对

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int trie[N*32][2],cnt[N*32],idx;
void insert(int x)
{
        int p=0;
        for(int i=30;i>=0;--i)
        {
                int u=(x>>i)&1;
                if(!trie[p][u]) trie[p][u]=++idx;
                p=trie[p][u];
        }
}
int serach(int x)
{
       int p=0,res=0;
        for(int i=30;i>=0;--i)
        {
                int u=(x>>i)&1;
                if(trie[p][!u]) 
                {
                        res+=(1<<i);p=trie[p][!u];
                }
                else p=trie[p][u];
        }
        return res;
}
int main()
{
    int n;scanf("%d",&n);
    int maxn=0;
    for(int i=0;i<n;++i)
    {
            int x;scanf("%d",&x);
            insert(x);
        maxn=max(maxn,serach(x))  ;
    }
    printf("%d\n",maxn);
}

144. 最长异或值路径

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int head[N],edge[N*2],ver[N*2],ne[N*2],tot;
int trie[N*32][2],f[N],idx;
void add(int x,int y,int z)
{
    ver[tot]=y;edge[tot]=z;
    ne[tot]=head[x];head[x]=tot;tot++;
}
void dfs(int k,int fa)
{
    for(int i=head[k];~i;i=ne[i])
    {
        int j=ver[i];
        if(j==fa) continue;

        f[j]=f[k]^edge[i];
        dfs(j, k);
    }
}
void insert(int x)
{
    int p=0;
    for(int i=30;i>=0;--i)
    {
        int u=(x>>i)&1;
        if(!trie[p][u])
        {
            trie[p][u]=++idx;
        }p=trie[p][u];
    }
}
int search(int x)
{
    int p=0,res=0;
    for(int i=30;i>=0;--i)
    {
        int u=(x>>i)&1;
        if(trie[p][u^1])
        {
            res+=(1<<i);p=trie[p][u^1];
        }else p=trie[p][u];
    }
    return res;
}
int main()
{
    int n;scanf("%d",&n);
    memset(head, -1, sizeof head);
    for(int i=0;i<n-1;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    dfs(0,-1);int maxn=0;
    for(int i=1;i<=n;++i)
    {
        insert(f[i]);
        maxn=max(maxn,search(f[i]));
    }
    printf("%d\n",maxn);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值