2022-11-13 Acwing每日一题
本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的。同时也希望文章能够让你有所收获,与君共勉!
字典树
今天来学习字典树Trie,Trie树主要支持两个操作,一个是构建Trie时需要的插入操作Insert
,另一个是查询操作query
。
首先来看看什么是字典树Trie,标准的Trie树是字符串组成的,结点是每个字符。图片来自这里。
如果是数组来模拟Trie树,就是这样。
既然是树,那么必然存在一个根节点,只不过这里是虚拟节点root,由于小写字符总共有26个,因此总共有26个子节点。数组是这样定义的:son[p][u]
,其中p可以认为Trie树的深度(从根节点开始算,root为-1层),也可以理解为p服从某种顺序。u是该层所存储的东西,可以是数字也可以是字母(需要映射为数字),而son[p][u]
就可以理解为第p层上的字母u的下一层索引
(,对于u
来说其是固定的,如果存在该字符我们就可以直接使用并通过son[p][u]
获得该字符下一层所对应的结点索引),除此之外还有一个idx
,它的作用类似一个线性表的在当前位置上的索引,具体作用看代码,这样对于每一个字符就得到了一个具体而准确的定位。
Trie的insert
操作:
主要分两种情况,从0开始遍历层数,如果下一层存在该字符,就继续往下走,如果不存在就在下一层该字符处创建新的索引。
Trie的query
操作:直接从根节点遍历Trie树,如果某一个字符存在就会自己往下走,否则不存在就可以直接返回。
这就是Trie树的主体,如果对于每个单词,我们想知道他们出现的次数,我们还可以定义
cnt
数组,来标记第p层存在单词,并且用来表示存在几个单词,而对于是否存在单词我们是在遍历过程中才能发现的,如果不存在某一个单词,那么遍历都不会完成,深度也不会达到p的。
代码表示
#include <iostream>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100000,idx;
int son[N][26],cnt[N];
int n;
void insert(char* s){
int p = 0;
for(int i=0; s[i] ; ++i){
int u = s[i] - 'a';
if(!son[p][u]) son[p][u] = ++idx;
// idx可以看成是深度所形成的线性表的下标,++idx在第一次循环就表示根节点在第0层,第一个结点在第一层
p = son[p][u]; // 就是去下一层
}
cnt[p] ++;
}
int query(char *s){
int p = 0;
for(int i=0 ; s[i] ; ++i){
int u = s[i] - 'a';
if(!son[p][u]) return 0;
p = son[p][u];
}
return cnt[p];
}
int main()
{
cin >> n;
while (n -- ){
char op[2];
char s[N];
scanf("%s%s",op,s);
if(*op == 'I'){
Insert(s);
}
else{
cout << Query(s) << endl;;
}
}
return 0;
}
最大异或对
在给定的 N 个整数 A1,A2……AN 中选出两个进行 xor(异或)运算,得到的结果最大是多少?
输入格式
第一行输入一个整数 N。
第二行输入 N 个整数 A1~AN。
输出格式
输出一个整数表示答案。
数据范围
1≤N≤105,
0≤Ai<231
输入样例:
3
1 2 3
输出样例:
3
算法原理
遇到题我们先思考暴力怎么求解,然后再针对每一步考虑使用合适的数据结构,对于最大异或对我们先考虑暴力双重循环,两两之间比较异或值,最后选出最大的,核心代码max(res,a[i]^a[j])
(其中^
是异或运算符),但这个算法的时间复杂度太高,\(O(n^2)\),因此我们需要思考怎么进行优化,我们发现最外层遍历每一个数字不能优化,内层我们需要找出外层固定的这个数字的最大异或值,那么我们就是要针对找到最大异或值这一部分进行优化。我们知道两个数字的异或运算就是对位相反取1,相同取0,如2:10,3:11,2^3:01。那么什么时候取最大值呢,我们发现当每一位都位1时所对应的数字是最大的,高位为1时的数字比低位为1时要更大,所以对位相反时进行异或结果是最大的,我们更希望每一位都相反,因此我们可以先寻找是否存在该数字的最大异或值,这时我们就可以使用Trie树进行寻找,先来看个图就理解为什么要用Trie树啦。图片来自这里
这样做的话找到的不就是该数组存储的所有数中最大的异或值了嘛。
代码实现
#include <iostream>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3300000;
int son[N][2],a[N]; // 只有0和1两个数,因此是二叉树且默认所有结点的下一层都为第0层(即不存在下一层)
int idx;
void insert(int x){ // 插入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];
}
}
int search(int x){ // 查询x的最大异或数
int p = 0;
int ans = 0; // 所有位默认为0
for(int i=30; i>=0 ; --i){
int u = x >> i & 1; // 取出第i位
// 判断是否存在对位,如果存在就往下走,否则就走另一个
if(son[p][!u]) {// 存在对位,说明该位可以是最大的,因此该位为1
ans += 1<<i; // 把1向左移到第i位
p = son[p][!u]; // 走的不是原来的位置,而是对位
}
else{ // 不存在对位,所以该位就是0
p = son[p][u]; // ans为0说明当前该位默认为0,直接移到下一位
}
}
return ans;
}
int main()
{
int n;
cin >> n;
int x;
for(int i=0; i < n; ++i){
cin >> a[i];
insert(a[i]);
}
int res= 0;
for(int i=0; i<n ; ++i) // 找到每一个数的最大异或值,再找到所有的数的最大异或值
{
res = max(res,search(a[i]));
}
cout << res << endl;
return 0;
}
2022-11-13 Acwing每日一题的更多相关文章
- [ 9.13 ]CF每日一题系列—— 340A GCD & LCM
Description: [ 着实比较羞愧,都想着去暴力,把算法(方法)也忘了] A只涂x,2x,3x……,B只涂y,2y,3y……问你A和B共同涂的墙的个数 Solution: 就是求x和y的lcm ...
- CISP/CISA 每日一题 13
监控信息系统人员所提供服务的效率和效果的工具: 1.例外报告:识别所有没有成功完成的或出了故障的应用 2.作业重运行报告:大多数异常终止作业都会导致重起 3.操作员问题报告:记录计算机运行问题及解决方 ...
- CISP/CISA 每日一题 11
CISA 每日一题(答) 一个合理建造的数据仓库应当支持下列三种基本的查询格式: 1.向上溯源和向下溯源——向上溯源是对数据进行总计:向下溯源是将数据进行细化: 2.交叉溯源——通过通用属性访问数据仓 ...
- 老男孩IT教育-每日一题汇总
老男孩IT教育-每日一题汇总 第几天 第几周 日期 快速访问链接 第123天 第二十五周 2017年8月25日 出现Swap file….already exists以下错误如何解决? 第122天 2 ...
- CISP/CISA 每日一题 五
CISA 每日一题(答) 信息系统审计师要确认系统变更程序中的: 1.变更需求应有授权.优先排序及跟踪机制: 2.日常工作手册中,明确指出紧急变更程序: 3.变更控制程序应同时为用户及项目开发组认可: ...
- [每日一题]面试官问:谈谈你对ES6的proxy的理解?
[每日一题]面试官问:谈谈你对ES6的proxy的理解? 关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
- 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素
[python]Leetcode每日一题-寻找旋转排序数组中的最小元素 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...
- 【JavaScript】【dp】Leetcode每日一题-解码方法
[JavaScript]Leetcode每日一题-解码方法 [题目描述] 一条包含字母 A-Z 的消息通过以下映射进行了 编码 : 'A' -> 1 'B' -> 2 ... 'Z' -& ...
- [LeetCode每日一题]153.寻找旋转排序数组中的最小值
[LeetCode每日一题]153.寻找旋转排序数组中的最小值 问题 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组 nums = [0,1, ...
- 【python】Leetcode每日一题-逆波兰表达式求值
[python]Leetcode每日一题-逆波兰表达式求值 [题目描述] 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说 ...
随机推荐
- KingbaseES 全局索引
概述:在分区表上创建的索引可分为全局索引和本地索引.全局索引包括全局非分区索引(Global Nonpartitioned Indexes)和全局分区索引(Global Partitioned Ind ...
- python 基于aiohttp的异步爬虫实战
钢铁知识库,一个学习python爬虫.数据分析的知识库.人生苦短,快用python. 之前我们使用requests库爬取某个站点的时候,每发出一个请求,程序必须等待网站返回响应才能接着运行,而在整个爬 ...
- Python图像处理丨带你认识图像量化处理及局部马赛克特效
摘要:本文主要讲述如何进行图像量化处理和采样处理及局部马赛克特效. 本文分享自华为云社区<[Python图像处理] 二十.图像量化处理和采样处理及局部马赛克特效>,作者: eastmoun ...
- 可靠的自托管「GitHub 热点速览 v.22.37」
自托管(Self-Hosted) 是很多开源项目主打的亮点:数据在手,安全我有.本周 GitHub 热点榜单上有多款自托管的项目,当中自然不能少了之前 HG 小伙伴 @makes world simp ...
- Nginx服务器性能优化与安全配置实践指南
转载自:https://www.bilibili.com/read/cv16151784?spm_id_from=333.999.0.0 1.引言 1.1 目的 为了更好的指导部署与测试艺术升系统ng ...
- tcmalloc 动态库替换(CentOS 操作系统)
Ceph 14.2.8版本中tcmalloc存在内存泄漏的问题,需要将tcmalloc pagesize调整为64,重新编译,替换tcmalloc动态库,该操作在三个Ceph存储节点上均需要执行. 步 ...
- nginx日志输出配置json格式
修改nginx配置文件 http { include mime.types; default_type application/octet-stream; charset utf-8; # 原有日志格 ...
- 【前端必会】webpack 插件,前进路绕不过的障碍
背景 webpack的使用中我们会遇到各种各样的插件.loader. webpack的功力主要体现在能理解各个插件.loader的数量上.理解的越多功力越深 开始 https://webpack.do ...
- 实验02_Proteus仿真数码管显示代码
一.原理总结 利用两个寄存器R4和R5来存储两个数码管的显示效果,R4是前一个数码管显示所需,而R5是后一个数码管显示所需,利用左移操作RLC来使之每一位被依次输入到C中,然后将C输入到LED中(当L ...
- 2022.9.30 Java第四次课后总结
1.public class BoxAndUnbox { /** * @param args */ public static void main(String[] args) { int value ...