最大异或和
一、字典树
用来高效的存储查找字符串集合 也可以存储二进制信息
- 存储
字典树存储形式如下:其中每个单词的末尾会做上一个 标记
查找
- 判断单词是否在路径上
- 如果在路径上,判断单词末尾是否存在标记
完整代码如下:
int son[N][26], cnt[N], idx;
// 0号点既是根节点,又是空节点
// son[][]存储树中每个节点的子节点, 26是假设仅有小写字母, 则每个节点的孩子最多为26个
// cnt[]存储以每个节点结尾的单词数量
// idx 表示每个节点的索引
// 插入一个字符串
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;
p = son[p][u];
}
return cnt[p];
}
二、字典树相关题目
143. 最大异或对
1. 异或和性质
异或被称为无进位加法,所以其与加法性质类似。
假设数 x
的二进制表示为 $x_n...x_1x_0$,数 y
的二进制表示为 $y_n...y_0$则二者的异或和为各位的异或结果乘以当前位的权值。即 $(x_n \bigoplus y_n) \times 2^n + ... + (x_0 \bigoplus y_0) \times 2^0$
2. 解体思路
由上述性质可知为找到与 x
异或和最大的数,应优先找到与其高位二进制位相反的值,这里可以利用 trie树
来存储每个数字的二进制位。 存储时应由高位往低位,优先找高位与此位不同的数。
样例字典树形式为:
完整代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e5, M = N * 31; // 字典树的深度最高为 N * 31
int son[M][2], idx; // 定义字典树
int n, q[N];
// 将一个数加入字典树中
void insert(int x) {
int p = 0;
for (int i = 30; i >= 0; i--) { // 从最高位开始遍历
int u = x >> i & 1; // 拿到x的第i位
if (!son[p][u]) son[p][u] = ++ idx; // 如果父节点没有这个孩子则插入
p = son[p][u]; // 更换父节点
}
}
// 查找与x异或和最大的一棵树
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 += 1 << i; } // 查找有没有与当前位相反的数存在
else p = son[p][u];
}
return res;
}
int main() {
int res = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &q[i]);
insert(q[i]);
res = max(query(q[i]), res);
};
printf("%d", res);
return 0;
}
3485. 最大异或和 - AcWing题库
算法要点: 将一段数的异或和最大值,转换为两个值的异或和最大值。
思路: 由于异或和具有类似加法的性质,所以可以采用类似前缀和的思路。
$$ 设:S_n = a_1 \bigoplus a_2 ... \bigoplus a_n \\ 则有:S_{i-1} \bigoplus S_{i...j} = S_j \\ 所以: S_{i...j} = S_j \bigoplus S_{i-1} $$
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10, M = N * 31; // 字典树的深度最高为 N * 31
int son[M][2], idx, cnt[M]; // 定义字典树
int n, m, s[N];
// 将一个数加入字典树中
void insert(int x, int v) {
int p = 0;
for (int i = 30; i >= 0; i--) { // 从最高位开始遍历
int u = x >> i & 1; // 拿到x的第i位
if (!son[p][u]) son[p][u] = ++ idx; // 如果父节点没有这个孩子则插入
p = son[p][u]; // 更换父节点
cnt[p] += v;
}
}
// 查找与x异或和最大的一棵树
int query(int x) {
int p = 0;
int res = 0;
for (int i = 30; i >= 0; i--) {
int u = (x >> i) & 1;
if (cnt[son[p][!u]]) { p = son[p][!u], res += 1 << i; } // 查找有没有与当前位相反的数存在
else p = son[p][u];
}
return res;
}
int main() {
int res = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &s[i]);
s[i] = s[i] ^ s[i - 1];
};
insert(s[0], 1);
for (int i = 1; i <= n; i++) {
if (i > m) insert(s[i - m - 1], -1); // 当i大于m时删掉距离当前大于m的数
res = max(res, query(s[i]));
insert(s[i], 1);
}
printf("%d\n", res);
return 0;
}
1 声望
0 粉丝
推荐阅读
万字长文剖析ChatGPT
简单来说,ChatGPT 是自然语言处理(NLP)和强化学习(RL)的一次成功结合,考虑到读者可能只熟悉其中一个方向或者两个方向都不太熟悉,本文会将 ChatGPT 涉及到的所有知识点尽可能通俗易懂的方式展现出来,有基...
xiangzhihong赞 15阅读 1.7k
数据结构与算法:二分查找
一、常见数据结构简单数据结构(必须理解和掌握)有序数据结构:栈、队列、链表。有序数据结构省空间(储存空间小)无序数据结构:集合、字典、散列表,无序数据结构省时间(读取时间快)复杂数据结构树、 堆图二...
白鲸鱼赞 9阅读 5.4k
openKylin 0.9.5版本正式发布,加速国产操作系统自主创新进程!
2023年1月12日,中国桌面操作系统根社区openKylin(开放麒麟)正式发布openKylin 0.9.5操作系统版本。此版本充分适应5G时代需求,打通平板,PC等设备,实现多端融合,弥补了国产操作系统的短板,有效推动国产操作...
openKylin赞 6阅读 8k
不会数学的程序员,只能走到初级开发工程师!
在我还是初级程序员时,每天也都粘贴着代码和包装着接口。那个阶段并没有意识到数学能在编程中起到什么作用,就算学了数学的部分知识,也没法用到编程中。但后来随着编程越来越久,逐步接手核心代码块开发时候,...
小傅哥赞 3阅读 998
杨辉三角的5个特性,一个比一个牛皮!
杨辉三角按照杨辉于1261年所编写的《详解九章算法》一书,里面有一张图片,介绍此种算法来自于另外一个数学家贾宪所编写的《释锁算书》一书,但这本书早已失传无从考证。但可以肯定的是这一图形的发现我国不迟于1...
小傅哥赞 3阅读 1.9k
stackoverflow 提问:“计算两个整数的最小公倍数的最有效方法是什么?”
作者:小傅哥博客:[链接]源码:[链接]沉淀、分享、成长,让自己和他人都能有所收获!😄一、前言嘿,小傅哥怎么突然讲到最大公约数了?这么想你肯定是没有好好阅读前面章节中小傅哥讲到的RSA算法,对于与欧拉结果...
小傅哥赞 3阅读 1.8k
DeepMind 发布强化学习通用算法 DreamerV3,AI 成精自学捡钻石
内容一览:强化学习是多学科领域的交叉产物,其本质是实现自动决策且可做连续决策。本文将介绍 DeepMind 最新研发成果:扩大强化学习应用范围的通用算法 DreamerV3。关键词:强化学习 DeepMind 通用算法
超神经HyperAI赞 1阅读 949
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。