【第十六课】哈希表(acwing-841字符串哈希 / 详解 / 优秀的文章推荐 / c++代码)

本文主要是介绍【第十六课】哈希表(acwing-841字符串哈希 / 详解 / 优秀的文章推荐 / c++代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

思想

代码如下

一些解释

1.基数P的选择

2.unsigned long long类型

可能需要看的文章博客


思想

咳咳,感觉这个刚开始第一遍接触的时候很抽象,,,还好网友们很强,有很通俗的解释办法hh。 

字符串的哈希核心思想是:我们把字符串当做一个P进制的数,有点像通过前缀和的思想得到两段字符串的哈希值,在判断两段字符串所映射的哈希值是否相同即可。

ha数组的每一位存的都是字符串的前 i 位映射之后的哈希值(这个哈希值的计算方式就是以P进制计算所得的数)。这里的P一般取131,13331 ,可以尽量避免冲突。(这个结论是在大量实践中得出的,我们平时使用直接记住就好。)

由于在进制数的运算中,通常需要求取次方,因此我们建立一个p数组,提前预处理出以P为基数的次方。方便后续的使用。

其实我们这里ha数组其实并不是哈希表,因为其元素表示的是哈希值,其下标表示的其实可以当作是字符串(因为下标是几表示的就是前缀到第几个字符的字符串)

也就是相比普通的哈希表下标表示哈希值,元素表示数据(回想一下840的散列表),也就是反过来了。

也就是说字符串哈希其实是运用到了哈希表的思想,其实实际的实现过程并不一定需要使用哈希表

哈希函数会将字符串映射到一个数字,这个过程并不需要哈希表。然而,如果想要存储和查找字符串,哈希表就可能会被用到,因为哈希表可以提供快速的查找速度

下面这张图也对解决字符串哈希的方式与我们所熟悉的十进制放在一起进行对照,相信可以理解哈。(这个英文字体好漂亮hh)

相信到这里,这种方法的思路应该是可以明白的.。

代码如下

#include<iostream>
using namespace std;const int N=1e5+10,P=131;
typedef unsigned long long ULL;int n,m;
char str[N];
ULL ha[N],p[N];//ha存储所有子串映射的哈希值  p数组存储 以 P 为进制数 的P的次方,方便加权求和
//ha数组的下标表示的就是前多少个字符  p数组的下标表示的就是对应多少次方ULL get(int l,int r)
{return ha[r]-ha[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;ha[i]=ha[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;
}

一些解释

1.基数P的选择

选择P=131作为基数的原因与ASCII码表有关。在字符串哈希中,我们通常会将字符串中的每个字符转换为其对应的ASCII码,然后使用这些ASCII码来计算哈希值(这个理解哈)。ASCII码的范围是0到127,因此我们需要选择一个大于127的数作为基数,以确保不同的字符串能够映射到不同的哈希值。

通过下面的例子也很清楚。 

2.unsigned long long类型

求每个前缀字符串的哈希值的方法明白了之后,我们就要想,求的时候一直在乘次方,将会导致这个映射的数特别大,也就是我们将要存进ha数组中的数会很大,为了避免数据溢出,我们当然可以定义一个特别大的数据类型来避免溢出,只是再大也会有超限的时候,因此要完成取模工作,关于对谁取模,这里又是一个经验值,一般是2^64,而恰好unsigned long long有溢出自动取模的功能,因此我们就采用了这种定义数据类型的方式。

也就是说我们完整的求出哈希值的步骤就是:按照进制算出数字,再进行取模操作,这才完成了一个哈希值的运算

关于取模这里也有一个简化:就是我们定义unsigned long long类型的变量,它可以存储0到2^64−1之间的整数。当一个unsigned long long类型的变量的值超过2^64−1时,它会自动溢出,也就是说,它会自动对2^取余。

3.不能将一个字符串映射成0,要从1开始映射

从0开始映射的话会增加冲突概率。因此我们从1开始

4.str数组要从1开始,为的是方便前缀和计算。

可能需要看的文章博客

讲的很好的文章,这个平台好像是有很系统的算法的文章。非常推荐

字符串哈希

这个博主写了哈希专题,也很清晰。

哈希专题 

之前写的普通的哈希算法

【第十六课】哈希表上篇

可能需要回顾的kmp算法

kmp算法


字符串哈希写的汗流浃背(bushi),感觉不太好理解,把抽象的理解了之后发现还有很多细节需要琢磨。

有问题欢迎指出!一起加油!! 

这篇关于【第十六课】哈希表(acwing-841字符串哈希 / 详解 / 优秀的文章推荐 / c++代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/644495

相关文章

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

详解nginx 中location和 proxy_pass的匹配规则

《详解nginx中location和proxy_pass的匹配规则》location是Nginx中用来匹配客户端请求URI的指令,决定如何处理特定路径的请求,它定义了请求的路由规则,后续的配置(如... 目录location 的作用语法示例:location /www.chinasem.cntestproxy

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

CSS will-change 属性示例详解

《CSSwill-change属性示例详解》will-change是一个CSS属性,用于告诉浏览器某个元素在未来可能会发生哪些变化,本文给大家介绍CSSwill-change属性详解,感... will-change 是一个 css 属性,用于告诉浏览器某个元素在未来可能会发生哪些变化。这可以帮助浏览器优化

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

C++变换迭代器使用方法小结

《C++变换迭代器使用方法小结》本文主要介绍了C++变换迭代器使用方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、源码2、代码解析代码解析:transform_iterator1. transform_iterat

详解C++中类的大小决定因数

《详解C++中类的大小决定因数》类的大小受多个因素影响,主要包括成员变量、对齐方式、继承关系、虚函数表等,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 非静态数据成员示例:2. 数据对齐(Padding)示例:3. 虚函数(vtable 指针)示例:4. 继承普通继承虚继承5.

C++中std::distance使用方法示例

《C++中std::distance使用方法示例》std::distance是C++标准库中的一个函数,用于计算两个迭代器之间的距离,本文主要介绍了C++中std::distance使用方法示例,具... 目录语法使用方式解释示例输出:其他说明:总结std::distance&n编程bsp;是 C++ 标准

前端高级CSS用法示例详解

《前端高级CSS用法示例详解》在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交互和动态效果的关键技术之一,随着前端技术的不断发展,CSS的用法也日益丰富和高级,本文将深... 前端高级css用法在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交

微信公众号脚本-获取热搜自动新建草稿并发布文章

《微信公众号脚本-获取热搜自动新建草稿并发布文章》本来想写一个自动化发布微信公众号的小绿书的脚本,但是微信公众号官网没有小绿书的接口,那就写一个获取热搜微信普通文章的脚本吧,:本文主要介绍微信公众... 目录介绍思路前期准备环境要求获取接口token获取热搜获取热搜数据下载热搜图片给图片加上标题文字上传图片