Trie树–高效的存储和查找字符串集合的数据结构

  1. 对于本数据结构需定义三个主要变量
    二维数组 son[N][26] 用于存储每个点的下一个位置
    一维数组 cnt[N] 用于存储以所在位置结尾的点所包含的单词个数
    变量 idx 用于标记被使用过的点
    (关于 idx 的理解:idx 从1开始依次挨个递增,在有数据的点的位置都用 idx 去标记)
  2. 注意为了方便存储将每个节点或下一个节点所存储的字母用 -‘a’ 转化为数字
  3. 步骤:
    插入函数:
    1. 首先定义根节点p
    2. 接着循环所插入的数组
    3. 将所插入数组中的字母转化为数字
    4. 接下来在son二维数组中查询p的子节点中是否存在所插入的数字
    若没有则新建子节点,然后将该节点的子节点作为新的根节点进行后续操作
    5. 最后将最终的子节点的位置进行标记,即在cnt数组中将该终节点+1,便于统计某点所有的单词个数
    查找函数:

    1. 前段步骤与插入函数类似,在发现所查找的在根节点的下一个不存在则直接退出
    2. 最后若所查找的单词在树中存在则输出其节点的单词数,即cnt[]在该点的对应值

代码:

//注释版
#include<iostream>
using namespace std;const int N = 100010;
int son[N][26];
int cnt[N]; //存储每个点为结尾的单词的个数
int idx;
char str[N];
//注意下标为零的点既是根节点,也作为空节点void insert(char str[]) {int p = 0;   //p定义为根节点,也就是最开始的指向位置for (int i = 0; str[i]; i++) {int u = str[i] - 'a';   //将str中的字符映射为1~26的字母序if (!son[p][u])    son[p][u] = ++idx;   //若所插入的数据在根节点的下一个位置不存在则新建一个后插入p = son[p][u];   //将所插入的新数据作为新的起始位置进行下一步操作}cnt[p]++;
}int query(char str[]) {int p = 0;for (int i = 0; str[i]; i++) {int u = str[i] - 'a';if (!son[p][u]) return 0;   //若所查找的在根节点的下一个不存在则直接退出else{p = son[p][u];}}return cnt[p];
}int main() {int n;cin >> n;while (n--) {char op[2];cin >> op >> str;if (op[0] == 'I')    insert(str);else{cout << query(str) << endl;}}return 0;
}
//无注释版
#include<iostream>
using namespace std;const int N = 100010;
int son[N][26];
int cnt[N];
int idx;
char str[N];void insert(char str[]) {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 str[]) {int p = 0;for (int i = 0; str[i]; i++) {int u = str[i] - 'a';if (!son[p][u]) return 0;else{p = son[p][u];}}return cnt[p];
}int main() {int n;cin >> n;while (n--) {char op[2];cin >> op >> str;if (op[0] == 'I')    insert(str);else{cout << query(str) << endl;}}return 0;
}

题:最大异或对

在给定的 N 个整数 A1,A2……AN 中选出两个进行 xor(异或)运算,得到的结果最大是多少?输入格式
第一行输入一个整数 N。
第二行输入 N 个整数 A1~AN。输出格式
输出一个整数表示答案。数据范围
1 ≤ N ≤ 105,
0 ≤ Ai < 231输入:
3
1 2 3
输出:
3

概念:求异或值时先将其转化为二进制,进行异或运算(同为0 不同为1),然后再转换为十进制的值。

首先,暴力做法:

int res = 0;    //定义异或最小值,最小即为0for (int i = 0; i < n; i++) {   //枚举第一个数for (int j = 0; j < i; j++) { //枚举第二个数res = max(res, a[i] ^ a[j]);}}

思路:在进行异或的判断时,从左往右,当左边的异或为1,即不相等时,异或后得到的值一定较大,根据这个可将处所比较数外的剩下的数分为第一位相同和第二位不同两类。
算法原理:将数对应的二进制按Trie树输入,两个数进行比较时,挑选不同的一边往下进行,此时所异或的值是最大的,若往下只有一条则往该条路进行(尽量往不同的位走
(在画Trie树时可默认为往右为1,往左为0)
代码:

//有注释版
#include<iostream>
#include<algorithm>
using namespace std;const int N = 100010,M = 31 * N;
int n;
int a[N];
int son[M][2], idx; //每个根节点对应的子节点最多有2个void insert(int x) {int p = 0;   //定义头节点for (int i = 30; i >= 0; i--) { //从最高位开始插入以便进行比较int u = x >> i & 1;  //将x的第i位二进制值赋给uif (!son[p][u])  son[p][u] = ++idx;   //当子节点不存在时即创建新的子节点p = son[p][u];}
}int query(int x) {int p = 0;int res = 0; //此处res定义的即为所查询的数与Trie树比较所得到的最大异或值for (int i = 30; i >= 0; i--) {  //从最高位开始进行比较int u = x >> i & 1;//在p根节点往下找跟u不同的数字,若有则往不同的方向走,若没有则只能往同方向走if (son[p][!u]) {p = son[p][!u];res = res * 2 + 1;   //*2相当于向右添加一位,将左边的所有位都*2,再加上新添加位的值即可}else{p = son[p][u];res = res * 2 + 0;}}return res;
}int main() {cin.tie(0);    //提高运行速度scanf("%d", &n);for (int i = 0; i < n; i++) {scanf("%d", &a[i]);}int res = 0;    //标记异或所得值的最大值for (int i = 0; i < n; i++) {    //先输入后查找,防止为空时的边界问题insert(a[i]);res = max(res, query(a[i]));}cout << res;return 0;
}

解释:(对同一i进行插入和查找)
对于for循环中的插入和查找操作,其顺序对结果无影响,先插入后查找和先查找后插入得到的结果一样,而此处先插入后查找可防止在Trie树中无数据时的边界情况,不用加以特判。并在for循环中对同一i进行插入和查找,在插入第一个时相异或为零,在接下来的插入和查找,查找的即为Trie树中的其他所有元素,所以不会是对同一i插入和查找异或值均为0的情况
关于cin.tie(0)
cin.tie(0)操作解除cin 和 cout关联(绑定时cin之前会将cout输出缓冲区的数据刷新到输出文件),可以避免当cout缓冲区的数据没有刷新到文件中时使用了cin,这样就可能发生数据不一致,通过绑定可以在输入前将cout数据输出的文件中。默认时绑定的。
解除与 c 输入输出stdio(scanf、printf)的联系,可以提升输入输出速率,但解除之后不能混合使用。

//无注释版
#include<iostream>
#include<algorithm>
using namespace std;const int N = 100010,M = 31 * N;
int n;
int a[N];
int son[M][2], idx;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;int 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;}else{p = son[p][u];res = res * 2 + 0;}}return res;
}int main() {cin.tie(0);scanf("%d", &n);for (int i = 0; i < n; i++) {scanf("%d", &a[i]);}int res = 0;for (int i = 0; i < n; i++) {insert(a[i]);res = max(res, query(a[i]));}cout << res;return 0;
}

3.Trie树(题:最大异或对)相关推荐

  1. 【bzoj3261】最大异或和 可持久化Trie树

    题目描述 给定一个非负整数序列 {a},初始长度为 N.        有M个操作,有以下两种操作类型: 1.A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1. 2.Q l r x: ...

  2. Trie树合并 + SG函数 ---- BZOJ4730. Alice和Bob又在玩游戏(动态开点Trie 树上全局异或标记 + 合并 + 博弈论)

    题目大题 题目大意: 解题思路: 首先我们对于子树u的SG函数为SG函数为SG函数为 ⨁是异或和\bigoplus是异或和⨁是异或和 SG[u]=mex{⨁w∈(w的父亲在u到v的路径上)SG[w]∣ ...

  3. P4735 最大异或和(可持久化trie树、求最大区间异或和)

    P4735 最大异或和 我们维护一个前缀异或和:s[i]=a[1]xora[2]xor-a[i−1]xora[i]s[i] = a[1] \ xor\ a[2]\ xor\ - a[i-1] \ xo ...

  4. 2021牛客暑期多校训练营4 E-Tree Xor(异或+思维+区间交 or Trie树)

    E-Tree Xor 首先不考虑区间限制条件,我们给定其中一个点的权值后,那么其他点的权值也就确定.比如 val1=0\text{val}_1=0val1​=0,即可通过变得限制求出其他点valu\t ...

  5. P4735 最大异或和 01可持久化Trie树模板

    原题:https://www.luogu.org/problemnew/show/P4735 题解:观察一下式子,将a数组求一个异或前缀和,其实就是s[n]^x^s[p-1]的最大值 p∈[l,r], ...

  6. BZOJ3261 最大异或和 解题报告(可持久化Trie树)

    本题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3261 题目描述 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类 ...

  7. 最大异或对[Trie树]

    最大异或对 题目大意:一些数中,选异或值最大的两个数,输出最大的异或值.数据范围1e5 暴力做法,O(N2)O(N^2)O(N2) 直接超时 #include<iostream> #inc ...

  8. 2017西安交大ACM小学期 有趣异或[Trie树]

    有趣异或 发布时间: 2017年7月4日 23:59   最后更新: 2017年7月5日 14:56   时间限制: 1500ms   内存限制: 512M 描述 给定n个非负整数,保证这些数两两不相 ...

  9. LeetCode 421. 数组中两个数的最大异或值(Trie树)

    1. 题目 给定一个非空数组,数组中元素为 a0, a1, a2, - , an-1,其中 0 ≤ ai < 231 . 找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i, ...

最新文章

  1. vue-cli3.0配置详解
  2. Python爬取网站用户手机号_设计师的福利,python爬取素材网站
  3. javascript有用小功能总结(未完待续)
  4. 帕雷诺的个展“共此时”在沪开幕 体验真实与虚妄的交错人生
  5. 雾霾的结构化责任主体
  6. Qt之小学徒学习记录分享
  7. 如何将docx文件制作为ftl模板
  8. 三端稳压管反向击穿情况及分析与防护措施
  9. 2021十大杰出现货黄金交易平台排名
  10. javaScript 上传图片(oss阿里云)
  11. 玩转5G之--初探5G网络模型(OSI模型和TCP/IP模型)
  12. Vertx中的verticle详解
  13. 关于报错Unknown custom element:did you register the component correctly? For recursive components的解决方式
  14. 计算机没有外审的核心期刊,国内核心期刊投稿经验总结战友们共同分享丁香园论坛...
  15. Java中英文字母的大小写转换ideaeclipse大小写快捷键
  16. 一周AI资讯|如果深度学习成为“侦探”,会发生什么?
  17. http请求报文及响应报文
  18. Linux ~ 计算机网络。
  19. RBA验厂辅导,RBA验厂取代EICC验厂社会责任验厂变化解决方案
  20. Excel忘记密码怎么办?VAB破解方法

热门文章

  1. 系统设计开发模式思考
  2. 人工智能的快速发展,对我们的不利影响有哪些?
  3. 华章IT图书书讯(2011年第6期)
  4. 实验二 货物进销管理系统
  5. 微信小程序点击图片预览真机无法显示的问题
  6. java程序 联机方法_Java实现Tank大战联机版
  7. 人脸检测和人脸识别原理
  8. 使用shape绘制阴影图层阴影效果
  9. Python爬取两个城市之间的直线距离
  10. 极光短信验证码的集成过程