Trie与可持久化Trie

Trie

Trie,也称为字典树或前缀树,是一种用于高效存储和检索字符串的树形数据结构。它的主要特点是利用字符串的公共前缀来减少存储空间和提高查询效率。下面是对 Trie 的常见操作的介绍:

插入(Insertion):将一个字符串插入到 Trie 中。从根节点开始,逐个字符检查字符串,并根据字符是否存在于当前节点的子节点中进行相应的操作。如果字符不存在,则创建一个新的节点并将其链接到当前节点的子节点上。

删除(Deletion):从 Trie 中删除一个字符串。与插入操作类似,逐个字符检查字符串并找到对应的节点。在删除操作中,我们需要注意保留 Trie 的结构完整性,即如果删除一个节点后,它的父节点没有其他子节点且不代表其他字符串的前缀,则需要将该父节点也删除。

查询(Search):在 Trie 中搜索一个字符串。从根节点开始,逐个字符检查字符串。如果所有字符都存在于 Trie 中并且最后一个字符对应的节点标记为字符串的结尾,则说明字符串存在于 Trie 中。

前缀搜索(Prefix Search):在 Trie 中搜索具有指定前缀的所有字符串。从根节点开始,逐个字符检查前缀。如果前缀的所有字符存在于 Trie 中,可以通过遍历 Trie 的子节点来找到所有以该前缀开头的字符串。

统计前缀数量(Count Prefixes):统计以指定前缀开头的字符串的数量。与前缀搜索类似,从根节点开始,逐个字符检查前缀,并跟踪到达前缀末尾的节点。然后可以遍历该节点的子节点,统计以该前缀开头的字符串的数量。

这些操作是 Trie 的基本操作,通过利用 Trie 数据结构的特点,我们可以在常数时间内执行这些操作,从而实现高效的字符串存储和检索。在实际应用中,Trie 在单词查找、前缀匹配、自动补全、拼写检查等领域都有广泛的应用。

例题 1:

在给定的 N个整数 A1,A2……AN中选出两个进行 xor(异或)运算,得到的结果最大是多少?

输入格式 第一行输入一个整数 N 第二行输入 N 个整数 A1~AN

输出格式 输出一个整数表示答案。

数据范围 1≤N≤105 0≤Ai<231

输入样例: 3 1 2 3

输出样例: 3

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
​
const int N = 1e5 + 10;
​
int tr[N * 30][2],idx;
int n;
int a[N];
​
void insert(int v)
{
    int p = 0;
    for(int i = 31; ~i; i --)
    {
        int c = v >> i & 1;
        if(tr[p][c] == 0) tr[p][c] = ++idx;
        p = tr[p][c];
    }
}
​
int query(int v)
{
    int p = 0;
    int ans = 0;
    for(int i = 31; ~i; i --)
    {
        int c = v >> i & 1;
        if(tr[p][!c])
        {
            ans += (1 << i);
            p = tr[p][!c];
        }
        else p = tr[p][c];
    }    
    
    return ans;
}
int main()
{
    cin >> n;
    
    for(int i = 1; i <= n; i ++ )
    {
        cin >> a[i];
        insert(a[i]);
    }
    
    int ans = -1 << 30;
    for(int i = 1; i <= n; i ++ )
    {
        ans = max(ans ,query(a[i]));
    }
    
    cout << ans;
    return 0;
}

可持久化Trie

可持久化 Trie 是一种基于 Trie 数据结构的扩展,它允许我们在 Trie 中保留历史版本,而不仅仅是对当前状态的操作。可持久化 Trie 可以有效地支持在不同版本之间进行查询和修改操作。

在传统的 Trie 数据结构中,每次插入或删除一个单词时,会直接在当前的 Trie 上进行操作,这导致了无法回溯到之前的状态。但是,在可持久化 Trie 中,我们会使用一种持久化的方式来记录 Trie 的每个版本,并保留了每个版本的所有修改操作。

在可持久化 Trie 中,每个节点都包含一个指向子节点的数组或指针,并且每个节点还记录了一个版本号。当需要进行插入或删除操作时,我们会创建一个新的节点来表示新的版本,并将变化应用到新的节点上,同时保留旧版本的节点不变。

通过这种方式,可持久化 Trie 实现了对历史版本的查询能力。我们可以根据需要回溯到任意一个版本,并进行相应的查询操作,而不会影响其他版本的数据。

可持久化 Trie 在许多应用中都具有重要的作用,例如字符串的版本管理、历史记录、文本编辑器的撤销/重做等。它提供了一种高效、可靠的方法来处理需要对数据结构进行时间旅行的场景。

需要注意的是,可持久化 Trie 在时间和空间上都会有一定的开销,因为每个版本都需要额外的空间来存储节点的副本。因此,在实际应用中,我们需要根据具体需求权衡时间和空间的利弊,选择是否使用可持久化 Trie。

总结起来,可持久化 Trie 是一种可以保留历史版本并支持回溯的 Trie 数据结构扩展,它提供了对历史状态的查询能力,适用于许多需要对数据结构进行时间旅行的应用场景。

参考:AcWing 256. 最大异或和 - AcWing

例题:

给定一个非负整数序列 a,初始长度为 N。有 M 个操作,有以下两种操作类型: A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N 增大 1 Q l r x:询问操作,你需要找到一个位置 p,满足 l≤p≤r,使得:a[p] xor a[p+1] xor … xor a[N] xor x 最大,输出这个最大值。

输入格式 第一行包含两个整数 N,M,含义如问题描述所示。 第二行包含 N 个非负整数,表示初始的序列 A 接下来 M行,每行描述一个操作,格式如题面所述。

输出格式 每个询问操作输出一个整数,表示询问的答案。 每个答案占一行。

数据范围 N,M≤3×105,0≤a[i]≤107

解题思路:

1.根据xor运算的性质,可以发现,用类似加法前缀和的方式维护异或和S数组同样成立

2.原问题转化为 已知整数val = s[N] xor x,求一个位置p (l - 1 <= p <= r - 1),使得s[p] xor val 最大

3.限制1: p <= r - 1,可直接用可持久化Trie维护,答案从root[r - 1]中找即可 

4.限制2: p >= l - 1,维护每个点的max_id。含义是:当前版本中 用来更新 当前点的 最大下标i

(p >= l - 1 等价于 最大的i 大于 l - 1)

递归实现 方便统计max_Id,读者可自行体会,事实上,每次执行insert都会重新开一个新的根节点,也就是新的版本。并递归的插入s[i]的每一个二进制位.对于所有新插入的节点而言,其max_id都会被更新为i;若不是新插入的点,则直接复制之前版本的信息,之前版本的信息中也包含了历史版本的max_id.

总之,查询某一个版本的trie时,所有新插入的点都会被更新为i,而旧的点则继承历史版本信息

#include <cstring>
#include <algorithm>
using namespace std;
​
const int N = 600010, M = N * 25;
​
int n,m;
int tr[M][2],max_id[M],idx;
int root[N];
int s[N];

void insert(int i, int k, int p, int q)
{
    if(k < 0)
    {
        max_id[q] = i;
        return ;
    }
​
    int v = s[i] >> k & 1;
​
    if(p) tr[q][v ^ 1] = tr[p][v ^ 1];
    //p存在的话,将与当前扩展节点相反的历史版本直接复制过来
    tr[q][v] = ++ idx;
​
    insert(i, k - 1, tr[p][v], tr[q][v]);
    max_id[q] = max(max_id[tr[q][0]], max_id[tr[q][1]]);
}
​
int query(int root, int C,  int L)
{
    int q = root;
​
    for(int i = 23; ~i; i --)
    {
        int v = C >> i & 1;
        //如果当前节点的相反节点 node
        //如果node是由 >= L的版本更新
        if(max_id[tr[q][v^1]] >= L)
        {
            q = tr[q][v^1];
        }
        else q = tr[q][v];
    }
​
    return C ^ s[max_id[q]];
}
​
int main()
{
    cin >> n >> m;
    //0也是合法方案
    root[0] = ++idx;
    max_id[0] = -1;
    //23是因为1e7的数据范围
    insert(0, 23, 0, root[0]);
​
    for(int i = 1; i <= n; i ++ )
    {
        int a; cin >> a;
        s[i] = s[i - 1] ^ a;
​
        root[i] = ++idx;
        insert(i, 23, root[i - 1], root[i]);
    }
​
    for(int i = 1; i <= m; i ++ )
    {
        char op[2];
        scanf("%s", op);
​
        if(op[0] == 'A')
        {
            int x; cin >> x;
            n ++;
            s[n] = s[n - 1] ^ x;
            root[n] = ++idx;
            
            insert(n, 23, root[n - 1], root[n]);
        }
        else
        {
            int l,r,x;
            cin >> l >> r >> x;
            int val = x ^ s[n];
            cout << query(root[r - 1], val, l - 1) << endl;
        }
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/21716.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Deformable DETR 论文学习

1. 解决了什么问题&#xff1f; DETR 去除了目标检测算法中的人为设计&#xff0c;取得了不错的表现。但是其收敛速度很慢&#xff0c;对低分辨率特征识别效果差&#xff1a; 模型初始化时&#xff0c;注意力模块给特征图上所有的像素点分配的权重是均匀的&#xff0c;就需要…

元宇宙应用领域-工业

元宇宙是指虚拟空间的总称&#xff0c;在这个虚拟空间中&#xff0c;用户可以像在现实世界一样&#xff0c;通过虚拟现实技术进行交互和体验。元宇宙应用领域非常广泛&#xff0c;如工业、游戏、娱乐、教育、医疗、房地产等。 工业领域中&#xff0c;元宇宙可用于在设计阶段帮…

物联网应用普及正在改变我们的生活

物联网&#xff08;Internet of Things&#xff0c;IoT&#xff09;指的是通过互联网连接各种物品、设备和传感器&#xff0c;实现物品之间的互联互通&#xff0c;形成智能化、自动化的数据交互和服务体系。简单来说&#xff0c;就是将各类物品通过互联网连接&#xff0c;实现互…

新榜 | “淄博”现象专项观察报告

在过去的一个月中&#xff0c;淄博烧烤的相关话题霸屏网络&#xff0c;这些媒介话题里承载了多少受众的向往与想象&#xff1f; 根据2022年淄博市文旅局公开年报&#xff0c;去年&#xff0c;淄博官方就着力融媒体&#xff0c;在抖音、快手等平台创新使用“淄博到底有多牛”主题…

智能图像处理技术:开启未来视觉时代

写在前面技术论坛■ 智能文档图像处理技术■ 大模型时代的文档识别与理解■ 篡改文本图像的生成与检测 圆桌讨论未来愿景 写在前面 文档 是人们在日常生活、工作中产生的信息的重要载体&#xff0c;各领域从业者几乎每天都要与金融票据、商业规划、财务报表、会议记录、合同、…

react类组件生命周期基础总结

组件的生命周期是指组件从被创建到挂载到页面中运行起来&#xff0c;再到组件不用时卸载的过程&#xff0c;只有类组件才有生命周期&#xff08;类组件 实例化 函数组件 不需要实例化&#xff09; 生命周期新版本和旧版本的对比图如下&#xff1a; 生命周期&#xff08;constr…

GPT专业应用:撰写工作简报

●图片由Lexica 生成&#xff0c;输入&#xff1a;Workers working overtime 工作简报&#xff0c;作为一种了解情况、沟通信息的有效手段&#xff0c;能使上级机关和领导及时了解、掌握所属部门的政治学习、军事训练、行政管理等方面的最新情况&#xff1b;同时&#xff0c;能…

非暴力沟通模型

非暴力沟通模型 非暴力沟通的创始人是马歇尔.卢森堡&#xff0c;师从人本主义心理学之父卡尔.罗杰斯。《非暴力沟通》一书入选香港大学推荐的50本必读书籍之列。 模型介绍 非暴力沟通&#xff08;英文名称&#xff1a;NonviolentCommunication&#xff0c;简称NVC&#xff09;…

运行时栈帧结构与方法调用

1 运行时栈帧结构 Java虚拟机以方法作为最基本执行单元&#xff0c;“栈帧”则是用于支持虚拟机进行方法调用和方法执行背后的数据结构。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。 1.1 局部变量表 局部变量表的容量以变量槽为最小单位。 Java…

JSDoc 拥抱 Javascript

JSDoc 在 vs code 已经内置了. 可以在 js 文件的开头添加 // ts-check 即可. 在注释中标注来实现一些 ts 的功能. JSDoc 支持以下注解. Types typeparam (or arg or argument)returns (or return)typedefcallbacktemplate Classes Property Modifiers public, private, p…

Windows Server 2016 中文版、英文版下载 (updated May 2023)

Windows Server 2016 中文版、英文版下载 (updated May 2023) Windows Server 2016 Version 1607&#xff0c;2023 年 5 月更新 请访问原文链接&#xff1a;https://sysin.org/blog/windows-server-2016/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者…

ChatGPT + MindShow 制作PPT

&#x1f34f;&#x1f350;&#x1f34a;&#x1f351;&#x1f352;&#x1f353;&#x1fad0;&#x1f951;&#x1f34b;&#x1f349;&#x1f95d; ChatGPT MindShow 制作PPT 文章目录 &#x1f350;具体操作&#x1f433;结语 &#x1f350;具体操作 ChatGP…

2023—Unity打包Pico4(3)全流程(Pico插件)

一、项目选择了2021.3.0版本的URP&#xff0c;把项目Build成Android 二、打开Project Setting→ 安装最下面的XR Plugin Management 安装完成后的界面&#xff0c;此时还没有Pico选项出现 三、我们需要在该网站下载Pico的SDK包 picoxr/VRTK-Support (github.com) 解压该文件到…

python + windQuant:挑选公司

给定一些k线选股指标&#xff0c;如何挑选符合条件的公司&#xff0c;以python windquant为例&#xff1f; 【申明&#xff1a;本例只用来作为python学习交流之用&#xff0c;切勿以此作为投资的选股条件】 0、用以下条件挑选公司&#xff1a; 仅作示例用&#xff1a; 【1】…

qiankun + Vite + React + Vue + Angular 快速构建前端微服务

文章目录 一、主应用 vite二、微应用 react三、微应用 vue四、微应用 angular五、项目地址 一、主应用 vite npm npm create vitelatestyarn yarn create vite选择是否继续 Need to install the following packages:create-vite3.2.1 Ok to proceed? (y) y项目名称 Project…

nodejs进阶(3)—路由处理

1. url.parse(url)解析 该方法将一个URL字符串转换成对象并返回。 url.parse(urlStr, [parseQueryString], [slashesDenoteHost]) 接收参数&#xff1a; urlStr url字符串 parseQueryString 为true时将使用查询模…

四月成功上岸阿里,年后准备了两个月,要个21k应该不过分吧~

先说下我基本情况&#xff0c;本科不是计算机专业&#xff0c;现在是学通信&#xff0c;然后做图像处理&#xff0c;可能面试官看我不是科班出身没有问太多计算机相关的问题&#xff0c;因为第一次找工作&#xff0c;阿里的游戏专场又是最早开始的&#xff0c;就投递了&#xf…

github copilot chat申请,安装,及常见问题解决

申请 首先申请&#xff0c;并开通copilot, 地址为&#xff1a;https://github.com/features/copilot&#xff0c;copilot 一个月10美金&#xff0c;第一个月免费&#xff0c;支持国内的信用卡。 开通copilot之后&#xff0c;可以申请 copilot chat 的预览版功能&#xff0c;网…

DistilPose: Tokenized Pose Regression with Heatmap Distillation

论文名字&#xff1a;DistilPose&#xff1a;使用热图蒸馏的令牌化姿势回归 论文地址&#xff1a;2303.02455.pdf (arxiv.org)https://arxiv.org/pdf/2303.02455.pdf项目地址&#xff1a;yshMars/DistilPose: Implementation for: DistilPose: Tokenized Pose Regression with…