【第十六课】哈希表(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

相关文章

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Redis 的 SUBSCRIBE命令详解

《Redis的SUBSCRIBE命令详解》Redis的SUBSCRIBE命令用于订阅一个或多个频道,以便接收发送到这些频道的消息,本文给大家介绍Redis的SUBSCRIBE命令,感兴趣的朋友跟随... 目录基本语法工作原理示例消息格式相关命令python 示例Redis 的 SUBSCRIBE 命令用于订

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H