第二章 数据结构(三)

文章目录

  • 哈希表存储结构
    • 拉链法:
      • 插入
      • 查询
      • 题目
      • 注意
    • 开放寻址法
      • 查找质数
      • 代码
  • 字符串哈希方式
  • STL相关知识

哈希表存储结构

整体结构

image-20220730142231971

0~109->0~105

方法:

  1. x mod 105
  2. 处理冲突
    1. 开放寻址法
    2. 拉链法

拉链法:

思想:每个槽上拉一条链,用于储存该槽上所有数

image-20220730144039375

image-20220807161303758

插入

  1. 确定插槽
  2. 确定插槽链表

image-20220807154438054

  1. 插入至头节点

image-20220807154657917

查询

  1. 确定插槽
  2. 遍历插槽链表

题目

维护一个集合,支持如下几种操作:1.  `I x`,插入一个数 xx;
2.  `Q x`,询问数 xx 是否在集合中出现过;现在要进行 N 次操作,对于每个询问操作输出对应的结果。输入格式第一行包含整数 N,表示操作数量。接下来 N 行,每行包含一个操作指令,操作指令为 `I x`,`Q x` 中的一种。输出格式对于每个询问指令 `Q x`,输出一个询问结果,如果 xx 在集合中出现过,则输出 `Yes`,否则输出 `No`。每个结果占一行。数据范围1≤N≤1051≤N≤105
−109≤x≤109−109≤x≤109输入样例:
5
I 1
I 2
I 3
Q 2
Q 5
输出样例:
Yes
No
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100003;//e被拆成了很多链
int h[N],e[N],ne[N],idx;
//插入到链表头部
void insert(int x)
{//将k映射至题目范围int k = (x % N + N)%N;//插入:单链表插入//h[k]代表k链的头部节点,节点值为xe[idx] = x,ne[idx] = h[k],h[k] = idx++;
}
bool find(int x)
{int k = (x%N+N)%N;/*遍历,从头指针开始,头指针存储第一个结点的下标,e[i]表示当前节点的值是多少ne[i]下一个节点的下标空指针的下标为-1*/for(int i = h[k];i!=-1;i = ne[i])if(e[i] == x)return true;return false;
}int main()
{/*寻找大于100000的最小质数//1.确定范围for(int i =100000;;i++){//2. 设置标志位bool flag = true;//3. 从2开始查找,条件为平方小于ifor(int j = 2;j*j<=i;j++){if( i % j == 0 ){//4. 设置标志flag = false;break;}}//5. 判断标志if(flag){cout<< i<<endl;//6. 结束break;}}return 0;*/int n;scanf("%d",&n);//槽清空memset(h,-1,sizeof(h));while(n--){//注意此处为数组输入%schar op[2];int x;scanf("%s%d",op,&x);if(*op == 'I') insert(x);else{if(find(x)) puts("Yes");elseputs("No");}}
}

注意

  1. 取模计算

​ 负数模一个值等于该绝对值模值结果添加负号

-10 %3 = -1

​ 需要先模再加再模,才可以使得负数取模为正数。

开放寻址法

只开了一个一维数组,没有开辟链表,形式更为简单。

一维数组的长度经验来说开到题目的两到三倍

image-20220807162403617

如何处理冲突:从第k个坑位开始找,如果第k个坑位有人的话就查找下一个坑位

image-20220807162441973

一般题目只会用到查找与添加

添加

查找:从前向后找

删除:找到x后打个标记,表示x删除

维护一个集合,支持如下几种操作:1.  `I x`,插入一个数 xx;
2.  `Q x`,询问数 xx 是否在集合中出现过;现在要进行 N 次操作,对于每个询问操作输出对应的结果。输入格式第一行包含整数 N,表示操作数量。接下来 N 行,每行包含一个操作指令,操作指令为 `I x`,`Q x` 中的一种。输出格式对于每个询问指令 `Q x`,输出一个询问结果,如果 xx 在集合中出现过,则输出 `Yes`,否则输出 `No`。每个结果占一行。数据范围1≤N≤1051≤N≤105
−109≤x≤109−109≤x≤109输入样例:
5
I 1
I 2
I 3
Q 2
Q 5
输出样例:
Yes
No

查找质数

#include <iostream>using namespace std;
//开两倍
const int N = 200003;int main()
{//首先找到大于200000的质数for(int i = 200000;;i++){bool flag = true;for(int j = 2; j*j<=i ;j++)if(i%j ==0){flag = false;break;}if(flag){cout<<i<<endl;break;}}return 0;
}

得到结果为 200003

代码

#include <iostream>
#include <cstring>
using namespace std;
//N为大于2倍的最小质数,null为大于区间的一个值,用于表示空
//一般设置最大值也设置0x3f3f3f3f
const int N = 200003,null = 0x3f3f3f3f;
int h[N];//find--寻找下一个坑位
int find(int x)
{//映射int k = (x % N + N) % N;//坑位有人并且不等于x//循环退出条件:找到值或者找到新的坑位//一定可以停止:因为数组大小较大while(h[k] != null && h[k] != x ){//向后查找下一个坑位k++;//如果已经到达结尾,循环看第一个坑位if(k == N) k = 0;}//如果x在哈希表中,k返回为下标;//如果不在哈希表中,k表示应该存储的位置return k;
}int main()
{int n;int x;char op[2];/*为什么memset 0x3f因为memset按字节进行,不是按数字初始化的,h是int型数组,一共有4个字节,每个字节都是0x3f,因此每个数是0x3f3f3f3f.一个字节是八位。memset(h,0,sizeof(h)); 每个字节是0,整体为0memset(h,-1,sizeof(h));  每个字节是-1(1111 1111),整体为-1*/memset(h,0x3f,sizeof(h));scanf("%d",&n);while(n--){scanf("%s%d",op,&x);int k = find(x);if(op[0] == 'I') h[k] = x;else {if(h[k] != null) puts("Yes");else puts("No");}}return 0;
}

字符串哈希方式

字符串前缀哈希法

步骤:

  1. 预处理所有前缀的哈希

    image-20220807190110127

    1. 如何定义某个前缀的哈希值

      把字符串看成P进制的数。

      假定映射关系如下表

      字母
      A1
      B2
      C3
      D4

      字符串“ABCD”对应的数值如下图所示:

      image-20220807190253141

    2. 预处理方式

      image-20220807195357489

    3. 将P进制的数转化为10进制的数;数字可能很大,通过取模进行映射到0,Q-1

      image-20220807190340950

注意:

  1. 不能把字母映射为0。不然不同的字符串均映射为0导致出错与冲突

    image-20220807190550973

  2. Rp【P进制】足够好,不存在冲突。经验值:131或13331

    image-20220807190819876

好处:可以利用前缀哈希,求得所有子串 的哈希值

image-20220807191002884

已知h[R]、h[L-1]

  1. h[L-1]左移至与R对齐

  2. 然后相减: h[R]-h[L-1]+PR-L+1

    image-20220807195004012

    image-20220807201510909

  3. Q:264

    用unsigned long long存储h,当数值溢出相当于取模,因此不需要取模

给定一个长度为 n 的字符串,再给定 m 个询问,每个询问包含四个整数 l1,r1,l2,r2,请你判断 [l1,r1] 和 [l2,r2] 这两个区间所包含的字符串子串是否完全相同。字符串中只包含大小写英文字母和数字。输入格式
第一行包含整数 n 和 m,表示字符串长度和询问次数。第二行包含一个长度为 n 的字符串,字符串中只包含大小写英文字母和数字。接下来 m 行,每行包含四个整数 l1,r1,l2,r2,表示一次询问所涉及的两个区间。注意,字符串的位置从 1 开始编号。输出格式
对于每个询问输出一个结果,如果两个字符串子串完全相同则输出 Yes,否则输出 No。每个结果占一行。数据范围
1≤n,m≤105
输入样例:
8 3
aabbaabb
1 3 5 7
1 3 6 8
1 2 1 2
输出样例:
Yes
No
Yes
#include <iostream>
#include <string>typedef unsigned long long ULL;const int N = 100010,P = 131;int n,m;
char str[N];
/*
p数组用来存储p的多少次方的数值,p的0次方等于1
h数组表示某个前缀的哈希值,h[R]表示前R个字母的哈希值
*/
ULL h[N],p[N];
ULL get(int l,int r)
{return h[r] - h[l-1] * p[r-l+1];  //部分区间长度计算公式
}
int main()
{scanf("%d%d%s",&n,&m,str + 1);p[0] = 1;for(int i = 1;i <= n ;i++){p[i] = p[i-1] * P;  //填充进制 P的一次方 P的二次方h[i] = h[i-1] * P+ str[i];  //填充前缀和}while(m--){int l1,r1,l2,r2;scanf("%d%d%d%d",&l1,&r1,&l2,&r2);if(get(l1,r1) == get(l2,r2)) puts("Yes");else puts("No");}return 0;
}

STL相关知识

/*
vector:变长数组,数组长度动态变化,倍增的思想
string:字符串,substr(),c_str()
queue:push(),front(),pop()
priority queue,优先队列,push(),top(),pop()
stack,栈,push(),top(),pop()
deque,双端队列
set,map, multiset,multimap,基于平衡树二叉树(红黑树)实现,动态维护有序序列
unordered_set,unordered_map,unordered_multiset,unordered_multimap,哈希表
bitset,压位
*/

一开始学习的时候,现用现查就可以了

vector的倍增思想

系统为某一个程序分配空间时,所需的时间基本上与空间大小无关,与申请次数有关

image-20220728215122098

vector数组长度不够时,新建一个二倍长度的数组,然后把之前的数据copy过来

/*知道存在该操作,用的时候现用现查
vector:变长数组,数组长度动态变化,倍增的思想size();  //返回元素个数empty();  //返回a是否为空clear():清空,这个函数不是所有容器都有front()/back()push_back()/pop_back()begin()/end()[] 随机取址支持比较运算
pair<int,int> 用于存储二元组first,第一个元素second, 第二个元素支持比较运算,以first为第一个关键字,以second为第二个关键字(字典序)pair与结构体相比有什么好处pair可以看作帮我们实现了一个结构体,自带一个比较函数,比一般结构体省代码可以存储任意多个,可以随便嵌套
string:字符串,substr(),c_str()size()/length() 返回字符串长度empty()clear()
queue:队列,队尾插入,队头弹出,先入先出的关系size()empty()push()  向队尾插入一个元素front()  返回队头元素back()  返回队尾元素pop()  弹出队头元素没有clear函数,如果需要清空一个queue,直接构造一个queue就可以定义时小根堆,多加两个参数priority_queue<int,vector<int>,greater<int>> heap;
priority queue,优先队列,默认时大根堆push(),插入一个元素top(),返回堆顶元素pop(),弹出堆顶元素
stack,栈,size()empty()push(),向栈顶插入一个元素top(),返回栈顶元素pop(),弹出栈顶元素
deque,双端队列size()empty()clear()front()back()push_back() / pop_back()push_front() / push_front()begin() / end()[]deque用的比较少,以为deque的效率低的令人发指,比一般的慢好几倍
set,multiset,map, multimap,基于平衡树二叉树(红黑树)实现,动态维护有序序列size()empty()clear()begin()/end() ++,--  返回前驱和后继 时间复杂度 O(logn)set/multisetset不支持插入重复元素multiset 支持插入重复元素insert() 插入一个数find() 查找一个数count() 返回某个数的个数erase()(1)输入是一个数,删除所有x  O(k + log(n))//k为数的个数(2)输入一个迭代器,删除这个迭代器lower_bound()/upper_bound()lower_bound(x) 返回大于等于x的最小的数的迭代器upper_bound(x) 返回大于x的最小的数的迭代器map/multimapinsert()   插入的数是一个pairerase()   插入的参数是pair或者迭代器find()[] 时间复杂度是O(logn)lower_bound()/upper_bound()unordered_set,unordered_map,unordered_multiset,unordered_multimap,哈希表和上面类似,增删改查的时间复杂度是O(1)不支持lower_bound()/upper_bound(),及迭代器的++ --
bitset,压位一个整数,4个字节,32位,很多题目压位计算bitset1024 bool数组 C++中一个bool是一个字节1024B = 1KB移到位中去,只需要开128B,比正常数组省8倍内存bitset<10000> s; <>中为个数~s,&,|,^>>,<<==,!=[]count() 返回多少个1any/none()any() 判断是否至少有一个1none() 判断是否全为0set() 把所有位置置为1set(k,v) 将第k位变为vreset()  把所有位变为0flip()  等价于~flip(k)  把k位取反C++ Reference C++最权威语法
*/

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <unordered_map>
using namespace  std;int main()
{/*vector<int> a;vector<int> b(10);vector<int> c(10,-3);for(auto x :c )cout<<x<<endl;vector<int> a[10];//size与empty是所有元素都有的函数,所有容器都有//时间复杂度是O(1)的,不会说求size的时候遍历,而是有一个变量来存储sizea.size();  //返回元素个数a.empty();  //返回a是不是空的*//*vector遍历vector<int> a;for(int i = 0 ;i < 10;i++) a.push_back(i);for(int i = 0;i<a.size();i++) cout<<a[i]<<' ';cout<<endl;//迭代器可以看做是指针,使用*解引用//for(vector<int>::iterator i = a.begin();i != a.end();i++) cout<<*i<<' ';//auto关键字,系统自动推断类型,当类型特别长时,用auto很省事for(auto i = a.begin();i != a.end();i++) cout<<*i<<' ';cout<<endl;//a.begin==a[0] a.end()==a.[a.size()]//C++中范围遍历for(auto x : a) cout<<x<<' ';cout<<endl;return 0;//比较运算。按照字典序进行比较vector<int> a(4,3),b(3,4);if(a < b) puts("a<b");*//**  pair<int,string> p;*  某个东西有两个不同的属性,就可以用pair存储,可能需要按照某一个属性排序p.firstp.second有三个属性也可以用pair存储pair<int,pair<int,int> > ppair<int,string> p;p = make_pair(10,"jgy");p = {20,"abc"};* *//** string a = "yxc";a += "def";a += 'c';//  cout<< a <<endl;//含义:下标从1开始,返回n个字母;当n大于数组长度时,输出到字符串最后一个字符为止//     把第二个参数省略,返回从1开始的整个子串// cout<<a.substr(1,10)<<endl;printf("%s\n",a.c_str());* *//*queue清空* queue<int> a;a = queue<int>();* *//* heap默认大根堆*   priority_queue<int> heap;* 如果要使用小根堆,* 1. 直接插入-x* 2. 定义时直接定义为小根堆,多加两个参数*  //小根堆priority_queue<int,vector<int>,greater<int>> heap;* *//*集合* set<int> s;multiset<int> ms;* *//*map*     map<string ,int> a;a["yxc"] = 1;cout<<a["yxc"]<<endl;* *//*unordered_map<string,int > a;unordered_multimap<string,int > b;return 0;* *//*bitset* 10000*10000 bool* 10的8次方 100MB空间  题目限制64M* bitset 12M足够了* */}

bitset

1024 bool数组 C++中一个bool是一个字节

1024B = 1KB

移到位中去,只需要开128B

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vaadin 10+作为CUBA UI的未来

从一开始&#xff0c;Vaadin就成为CUBA平台用户界面的基石和重要组成部分。 由于其创新的方法&#xff0c;它帮助CUBA将企业用户界面开发带到了一个非常有希望的&#xff08;如今是默认&#xff09;的WEB领域。 Vaadin最令人兴奋的部分之一是整个开发都是同构的&#xff0c;并且…

第二章 数据结构(一)

文章目录整体结构为什么用数组链表与邻接表单链表存储插入插入至头结点将x插入到下标为k的点后面删除遍历双链表初始化插入删除邻接表栈和队列栈队列单调栈单调队列KMP整体结构 链表与邻接表&#xff08;用数组模拟&#xff09;栈与队列&#xff08;用数组模拟&#xff09;kmp…

第三章搜索与图论(一)

文章目录DFS与BFS区别DFS全排列n皇后BFS树和图的遍历树和图的存储数和图的遍历深度优先遍历宽度优先遍历图的宽搜应用框架DFS与BFS区别 DFS: 执着&#xff1a;一直走到头&#xff0c;回去的时候边回去边看能不能向下走 BFS: 稳重&#xff1a;每次只扩展一层&#xff0c;不会…

第三章 搜索与图论(二)

文章目录最短路朴素Dijkstra算法堆优化版的Dijkstra算法Bellman-Ford算法SPFA算法求距离判负环Floyd最短路 并不区分有向图和无向图&#xff0c;因为无向图是一种特殊的有向图。直接用有向图的算法&#xff0c;解决无向图的问题。 常见情况可以分为两大类 在图论中&#xff0…

第三章 搜索与图论(三)

文章目录朴素版PrimKruskal算法染色法匈牙利算法朴素版Prim 给定一个 n 个点 m 条边的无向图&#xff0c;图中可能存在重边和自环&#xff0c;边权可能为负数。求最小生成树的树边权重之和&#xff0c;如果最小生成树不存在则输出 impossible。给定一张边带权的无向图 G(V,E)&a…

CDF 图的含义

CDF 图用于创建经验累积分布函数图。 使用 CDF 图可以确定等于或小于 x 轴上的给定值的数据的百分比。 例如&#xff0c;在该 CDF 图中&#xff0c;大约 34% 的数据小于总脂肪值 10 克。 参考链接 1. https://www.jmp.com/support/help/zh/14-2/ba-distribution-22.shtml

rome rss_RSS阅读器使用:ROME,Spring MVC,嵌入式Jetty

rome rss在这篇文章中&#xff0c;我将展示一些创建Spring Web应用程序的指南&#xff0c;这些应用程序使用Jetty并使用名为ROME的外部库运行RSS来运行它。 一般 我最近创建了一个示例Web应用程序&#xff0c;充当RSS阅读器。 我想检查ROME以阅读RSS。 我还想使用Spring容器和…

Ubuntu系统输入中文方式

我目前知道Ubuntu有两个还算好用的中文输入法&#xff1a; Fcitx&#xff1a;它是Linux世界开源的输入法框架&#xff0c;提供 Google PinYin、ShuangPin、SunPinYin、Wubi、ZhengMa、Hong Kong 和 TaiWan繁体等输入法。 1 安装Fcitx sudo apt install fcitx-pinyin fcit…

VMWare建立于W10的共享文件夹

一、共享文件夹建立 在虚拟机设置 -> 文件夹共享&#xff0c;选择总是启用&#xff0c;点击添加&#xff1a; 直接点击下一步&#xff1a; 选择原系统共享文件夹位置&#xff0c;并命名&#xff1a; 选择启用此共享&#xff0c;并继续&#xff1a; 二、VMtools安装 虚拟机…

VSCode如何去掉Monokai主题下的绿色下划线

VScode中类似sublime的主题为Monokai&#xff0c;但是自带主题Monokai中绿色下划线令人不舒服。 在网上寻找多种方式去除下划线。终于找到一种合适的处理方式。 1 安装主题插件 在主题插件中搜索One Monokai Theme&#xff0c;下载并安装 2 配置全局主题 通过快捷键“Ctr…

解决 ZLibrary 登录/注册不了的问题

一 文章转载链接内容 转载链接&#xff1a;解决 ZLibrary 登录/注册不了的问题 - 知乎 很多小伙伴反馈说 Z-Library 能打开&#xff0c;但是不能登录。这实际上是由于官方登录入口受限导致的。话虽如此&#xff0c;我们仍然可以通过某些方法绕过这个限制。 >虽然我们注册时…

gradle入门_Gradle入门:简介

gradle入门Gradle是一种构建工具&#xff0c;可以用基于Groovy编程语言的内部DSL替换基于XML的构建脚本。 最近它吸引了很多关注&#xff0c;这就是为什么我决定仔细研究一下。 这篇博客文章是我的Gradle教程的第一部分&#xff0c;它有两个目标&#xff1a; 帮助我们安装Gr…

排队论游乐场的游乐项目_外汇游乐场

排队论游乐场的游乐项目介绍 F X Playground是基于JavaFX的原型制作工具或实时编辑器&#xff0c;它消除了编译Java代码的步骤。 这个概念并不新鲜&#xff0c;例如在网络世界中&#xff0c;有许多HTML5 游乐场提供在线编辑器&#xff0c;使开发人员可以快速原型化或尝试各种Ja…

Node.js安装及环境配置之Windows篇

原博文链接&#xff1a;Node.js安装及环境配置之Windows篇 - 刘奇云 - 博客园 from:https://www.cnblogs.com/zhouyu2017/p/6485265.html 一、安装环境 1、本机系统&#xff1a;Windows 10 Pro&#xff08;64位&#xff09; 2、Node.js&#xff1a;v6.9.2LTS&#xff08;64位…

npm WARN logfile could not create logs-dir: Error: EPERM: operation not permitted, mkdir ‘地址

场景&#xff1a;在windows系统下&#xff0c;安装node之后&#xff0c;查看npm版本&#xff0c;报错如图所示&#xff1a; 原因&#xff1a;是node目录权限不够&#xff1b; 解决方法&#xff1a;找到node目录&#xff0c;右键属性 > 安全 > 设置users用户完全控制权限…

javafx 自定义控件_JavaFX技巧10:自定义复合控件

javafx 自定义控件用JavaFX编写自定义控件是一个简单直接的过程。 需要一个控件类来控制控件的状态&#xff08;因此命名&#xff09;。 外观需要控件的外观。 而且通常不是用于自定义外观CSS文件。 控件的一种常见方法是将其正在使用的节点隐藏在其外观类中。 例如&#xff0…

虚拟机与容器 的 区别

VM和容器都可以帮助您充分利用可用的计算机硬件和软件资源。容器是块中的新孩子&#xff0c;但VM已经并且将继续在各种规模的数据中心中非常受欢迎。 如果您正在寻找在云中运行自己的服务的最佳解决方案&#xff0c;您需要了解这些虚拟化技术&#xff0c;它们如何相互比较&…

经典 Linux 协议栈——网络子系统

目录&#xff1a; 1.Linux网络子系统的分层 2.TCP/IP分层模型 3.Linux 网络协议栈 4.Linux 网卡收包时的中断处理问题 5.Linux 网络启动的准备工作 6.Linux网络包&#xff1a;中断到网络层接收 7.总结 Linux网络子系统的分层 Linux网络子系统实现需要&#xff1a; l …

Java和JavaScript之间的区别

1.简介 我们将在本文中比较Java语言和JavaScript语言。 JavaScript由Netscape开发。 它最初是用于客户端的脚本语言&#xff0c;后来又用作客户端和服务器脚本的语言。 Java由James Gosling由Sun Microsystems开发。 这些天来&#xff0c;JavaScript在服务器中以node.js的形式使…

《汇编语言》王爽实验DOS 环境 Win10 配置

下载这两个软件。 软件链接百度网盘 请输入提取码 提取码: y1j4 1. 将debug.exe放入一个文件夹中&#xff0c;用英文名&#xff0c;不要用中文。 我这里放在E盘下的Debug文件夹。 2 然后安装DOSBox软件。 安装好后在其文件目录下找到DOSBox 0.74-3 Options.bat 打开这个文件&…