哈希简单解说

news/2025/10/4 23:38:25/文章来源:https://www.cnblogs.com/hm2nsite/p/19126068

这个哈希确实是啊。

这里不说各种冲突什么东西的证明,因为作者不会,看不懂。

你说说是谁把钢琴和弦乐放一块去的,我怎么飞起来了。

哈希

下面的定义都是不严谨的,这里仅是我的通俗解释。

哈希的基本原理是:把一个判断需要很多时间或空间资源的元素或者状态,通过某种函数变成一个特殊的值或者是什么易于比较的东西,来大大节约判断花销。

比较重要的一点是,我们可以比较快速的维护出各个状态的哈希值。这通常需要一些数据结构辅助或者是利用一些运算符的运算性质。

下文解说的都是把什么东西变成值的哈希。

这里把这个东西 \(S\) 变成值的函数称为哈希函数 \(H(S)\)

当然,我们不能保证 \(H(S)\) 一定会对两个不同的 \(S\) 输出不同的结果。我们称这种情况为“碰撞”。稍微想一下就可以发现,既然输入数据长度不固定,而输出的哈希值是一个用 unsigned intunsigned long long 存的数,这意味着哈希值是一个有限集合,而输入数据则可以是无穷多个,那么建立一对一关系明显是不现实的。所以“碰撞”是必然会发生的。

我们的工作就是去设计一个有着尽量小可能发生碰撞的哈希函数来做题。

序列哈希

最开始应该是从字符串哈希开始学的。

序列哈希的重要性质与单模哈希

我们定义一有序序列 \(a_1,a_2,\cdots,a_n\) 的哈希函数为

\[H(n)=\left ( \sum_{i=1}^n a_i \cdot base^{n-1} \right ) \bmod M \]

其中 \(base\) 是一个特殊选择的质数,\(M\) 是一个很大的质数模数。常取 \(base=31,M=10^9+7\)

你问为什么要这样取?因为大家发现这样产生碰撞的可能性很小。也就是经验之谈。

\(H\) 显然可以递推,也就是:

\[H(i)=\left ( H(i-1)\times base +s_i \right ) \bmod M \]

这个哈希函数有不少优点:

可拆性

我们可以通过进行前缀哈希在 \(O(n)\) 的时间内对 \(a\) 预处理,并在 \(O(1)\) 时间内得到 \(a\) 任何一个子串的哈希值。

考虑一个新序列 \(s\),我们从 \(1\)\(n\) 处理前缀哈希,计入数组 \(H(n)\) 中,也即是:

\[H(i) = (s_1 \cdot base^{n-1} + s_2 \cdot base^{n-2} + \cdots + s_i \cdot base^{0}) \bmod M \]

对于一个子串 \(s_{l,r}\),其哈希值为:

\[H(s_{l,r}) = (H(r) - H(l-1) \cdot base^{r-l+1}) \bmod M \]

怎么推的

假设我们要求解区间 \([l,r]\) 的哈希值,有下面两个式子,下面省略一下 \(\bmod \ M\)

\[H(r) = s_1 \cdot base^{0} + s_2 \cdot base^{1} + \cdots + s_r \cdot base^{r-1} \]

\[H(l-1) = s_1 \cdot base^{0} + s_2 \cdot base^{1} + \cdots + s_{l-1} \cdot base^{l-2} \]

如果把 \(H(l-1)\) 乘上 \(base^{\,r-l+1}\),它就会对齐到 \(H(r)\) 的高位:

\[H(l-1) \cdot base^{\,r-l+1} = s_1 \cdot base^{r-l+1-1} + \cdots + s_{l-1} \cdot base^{r-1} \]

此时:

\[H(r) - H(l-1)\cdot base^{\,r-l+1} \]

就只剩下:

\[s_l \cdot base^{0} + s_{l+1} \cdot base^{1} + \cdots + s_r \cdot base^{r-l} \]

于是:

\[H(s_{l,r}) = (H(r) - H(l-1) \cdot base^{r-l+1}) \bmod M \]

可并性

我们可以在知道序列 \(a,b\) 的长度及其哈希值时,在两者生成哈希值的 \(base,M\) 均相同的前提下,得到拼接后的序列 \(a+b\)\(b+a\) 的哈希值。

拼接串 \(a+b\) 的哈希值为:

\[H(a+b) = H(a) + H(b) \cdot base^{|A|} \bmod M \]

其中 \(|a|\) 为序列 \(a\) 的长度。

怎么推的

设有两个子串:

  • \(A = s[l_1 \dots r_1]\),长度 \(|A| = r_1-l_1+1\),哈希为 \(Hash(A)\)
  • \(B = s[l_2 \dots r_2]\),长度 \(|B| = r_2-l_2+1\),哈希为 \(Hash(B)\)

目标:计算拼接串 \(C = A+B\) 的哈希。


\[H(A) = s_{l_1} \cdot base^0 + s_{l_1+1}\cdot base^1 + \cdots + s_{r_1}\cdot base^{|A|-1} \]

\[H(B) = s_{l_2} \cdot base^0 + s_{l_2+1}\cdot base^1 + \cdots + s_{r_2}\cdot base^{|B|-1} \]

拼接串 \(C = A+B\) 的哈希为:

\[H(C) = H(A) + H(B) \cdot base^{|A|} \bmod M \]

/n

由上面的合并性质,我们注意到一个序列的哈希值是可以动态维护的,使用树状数组或线段树均可。

性质说完了,你可能注意到我们上面的哈希值都对一个固定的 \(M\) 取模,我们称这样的哈希为单模哈希,这种哈希比较容易被 hack,下面说点更牛的。但好像赛场上写这种也就够了?

双模哈希

如名字,我们选择两个不同的大模数 \(M_1, M_2\),分别计算哈希:

\[H_1(s) = \left(\sum_{i=1}^n s_i \cdot base^{\,n-i}\right) \bmod M_1 \]

\[H_2(s) = \left(\sum_{i=1}^n s_i \cdot base^{\,n-i}\right) \bmod M_2 \]

最终哈希值为一个二元组:

\[\left(H_1(s), H_2(s)\right) \]

只有当两个模数下都发生碰撞时才会误判,冲突概率大约是原来的平方级下降,总而言之就是更不容易被卡了!

当然你也可以用两个不同的 \(base\) 对一个相同的 \(M\) 取模算出来两个哈希值,也有相同的效果。

如果你不嫌麻烦,三模及以上的哈希也是可以的。

自然溢出哈希

我们直接让所有存储哈希值的变量为 unsigned intunsigned long long 类型,这样在计算时相当于随时都对着 \(2^{32}\)\(2^{64}\) 取模。

可以说比较好写一些?但由于取模的是个偶数,被卡的可能性也比较大。

字符串哈希

就是把上述理论中的序列换成字符串而已啦。

因为每个字符都有一个自己的 ASCII 码,于是和序列哈希是一模一样的。

例题

ABC331F

是线段树维护区间哈希值的例题。

还没有代码。

[CF???]

我咋就记住这俩题了。

集合哈希与多重集合哈希

简单的树哈希

今晚上写不完了(恼

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

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

相关文章

02-springIOC01-注解方式实现

02-springIOC01-注解方式实现$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");使用注解的方式实现IOC 定义两个实体类 /*** @ClassName Address* @Descriptio…

国内买机票的网站建设有啥好玩的网页游戏

简介 TensorFlow是由Google团队开发的一个开源深度学习框架,完全基于Python语言设计。它的初衷是以最简单的方式实现机器学习和深度学习的概念,结合了计算代数的优化技术,使计算许多数学表达式变得简单。 优势: 强大的计算能力…

网站开发的原理西安 房产网站建设

注意:进行实例之前必须完成nginx的源码编译。(阅读往期文章完成步骤) 1.编辑nginx的配置文件,修改内容 [rootlocalhost ~]# vim /usr/local/nginx/conf/nginx.conf 2.创建新目录/usr/local/nginx/conf.d/,编辑新文件…

Say 题选记(9.28 - 10.4)

P5363 [SDOI2019] 移动金币 Staircase-Nim 加计数。 首先怎么转化成 Staircase-Nim 呢,可以把每个金币右边到下一个金币中间那些空的地方看成这个金币的石子,那么每次金币的向左移动就是把石子从右边金币的堆移到左边…

专题网站建设策划方案浙江省住房和城乡建设厅官方网站

1.IDEA概述 IDEA全称InelliJ IDEA,是用于java语言开发的集成环境,它是业界公认的目前用于Java程序开发最好的工具。 集成环境:把代码编写,编译,执行,调试扽过多种功能综合到一起的开发工具。 下载:https…

做北京会所网站哪个好商城平台

文章目录 网络拓扑安装使用代理服务器设置隐藏者设置 使用古老的ccproxy实现代理服务器,仅做实验用途,禁止做违法犯罪的事情,后果自负。 网络拓扑 均使用Windows Server 2003系统 Router 外网IP:使用NAT模式 IP DHCP自动分配或者…

Excel表设置为细框线

Sub 设置为细框线()边框类型数组 = Array(xlEdgeLeft, xlEdgeTop, xlEdgeBottom, _xlEdgeRight, xlInsideVertical, xlInsideHorizontal)遍历已使用区域的每个单元格For Each 单元格 In ActiveSheet.UsedRangeFor Each…

US$28.5 CG A11DS 3 Buttons Wire Remote Used with CGDI K2 Remote Key Programmer 5pcs/lot

CG A11DS 3 Buttons Wire Remote Used with CGDI K2 Remote Key Programmer 5pcs/lot Package includes:5pc x CG A11DS 3 Buttons Wire Remote Pictures of CG A11DS 3 Buttons Wire Remote Used with CGDI K2 Remote…

延边网站开发depawo怎样提高网站权重

作者:Pablo Samuel Castro、Marc G. Bellemare 来源:Google AI Blog,机器之心摘要:在过去几年里,强化学习研究取得了多方面的显著进展。在过去几年里,强化学习研究取得了多方面的显著进展。这些进展使得智能体能够以超…

前端学习教程-VIte整合ECharts

ECharts 是一个强大的开源数据可视化库,而 Vite 是现代前端构建工具,两者结合可以高效开发数据可视化应用。本教程实现从创建 Vite 项目到使用 ECharts 实现各种图表。 一、环境准备 1. 创建 Vite 项目 首先确保已安…

月牙河做网站公司域名对网站排名的影响

2019独角兽企业重金招聘Python工程师标准>>> 软件的一处功能用到EasyUI的表单提交,返回一串字符串,这串字符串里有一段HTML代码,正常的情况下这段HTML代码里的双引号“ 是用 \ 转义过的。在IE中没问题,但是在Firefox和…

网站开发安全管理爬取漫画数据做网站

在项目管理中,图表作为一种直观的工具,帮助项目经理更有效的规划、监控和控制项目的各个方面,以下是项目经理常用的几张图表,它们在项目管理中发挥着至关重要的作用。 1、甘特图 甘特图(Gantt Chart)是最…

const不可改变解释

不能对const定义的变量本身重新赋值,但是可以通过其他方式更换变量里面的属性或元素(仅限对象类型和数组类型)。 “不能对const定义的变量本身重新赋值”这指的是 const 创建了一个只读的绑定(read-only binding)…

US$137.75 OTOFIX D1 One Year Update Service (Subsription Only)

OTOFIX D1 One Year Update Service (Subsription Only)1. Please send us the device serial number with picture to our Email 2. No Need Shipping. No refund service3. This is Only for Software Update, Witho…

在哪个平台做网站比较好义务网网站建设方案

工作中的焦虑 帮助团队建立复原力、处理不确定性和完成任务的8项策略 作者:阿德里安-戈斯蒂克、切斯特-埃尔顿和安东尼-戈斯蒂克 Anxiety at Work 8 Strategies to Help Teams Build Resilience, Handle Uncertainty, and Get Stuff Done By Adrian Gostick and…

地方门户网站的特点微信开发者模式在哪

从这个类中得到的类图,构划出了软件的大部分设计。 系统结构视图提供软件和整个系统结构最复杂的也是最优雅的描述。和通常的软件系统相比,在分布式嵌入系统中了解系统组件如何协同工作是非常重要的。毕竟,每个类图仅仅是一个系统的静态设计…

macOS Sequoia 15.7.1安全更新:修复字体解析器内存损坏漏洞

苹果发布了macOS Sequoia 15.7.1安全更新,修复了FontParser组件中的越界写入漏洞。该漏洞可能被恶意字体文件利用,导致应用程序意外终止或进程内存损坏。更新可通过Mac App Store或苹果官网下载获取。APPLE-SA-09-29…

AtCoder Beginner Contest 426 ABCDEF 题目解析

A - OS Versions 题意 有三种操作系统的版本,按发布时间顺序分别为 Ocelot、Serval、Lynx。 给定字符串 \(X, Y\),请判断版本 \(X\) 相比于版本 \(Y\) 的发布时间是否相同或更靠后(版本相同或更新)。 思路 直接判断…

前端学习教程-ElementPlus 教程

Element Plus 是基于 Vue 3 的企业级 UI 组件库,提供了丰富的预置组件,可帮助开发者快速构建高质量的前端界面。 一、安装 Element Plus 1. 环境要求Vue 3.0+ Node.js 14.0+2. 安装方式 (1)使用 npm 或 yarn 安装(…

镇江百度网站排名中交路桥建设有限公司官网

Linux磁盘管理(二):LVM的创建、格式化和使用 一、LVM原理回顾 LVM的工作原理进行一个总结: (1)物理磁盘被格式化为PV,空间被划分为一个个的PE (2)不同的PV加入到同一个VG中,不同PV的PE全部进入到了VG的PE…