字符串从入门到退竞(1)——哈希

哈希是将一个序列映射到一段整数区间的函数。

通常要求对于两个随机的等长的不同序列,哈希函数得到的值(以下简称 Hash 值)不同。

更概括地说,Hash 函数满足:

  1. 序列相同时,Hash 值一定相同
  2. 序列不同时,Hash 值大概率不同;若两个长度相等的不同字符串 Hash 值相同,我们称这是“哈希碰撞”。

实现

考虑各种原因,OI 上使用的哈希函数通常这样实现:

对于字符串 S,记其前缀 S1i 的哈希值为 Hi。形式上记 H0=0,则

Hi=Hi1×base+Si

或者,有封闭形式:

Hi=j=1iSj×baseij

容易发现,实际上是将序列视为一个以 base 为进制的数。

为了控制值域,一般对一个大质数取模,或者让它自然溢出。

OI 界普遍认为取 base13113331 难以在随机数据下发生哈希碰撞(来源未知)。

但是对着你的程序总是能构造数据卡掉你,见工具 anti-hash

快速求子串哈希值

对于比对两个序列的子串的情形,我们可以预处理哈希值做到单次 O(1)

参考定义,容易发现:

Hi..j=HjHi×baseji+1

预处理序列的前缀哈希值和 base 的幂即可。

利用快速子串哈希可以 O(n) 做字符串匹配、O(logn) 求两个串的最长公共前缀等。

也可以快速去重,不必存储原串。

二维哈希

随便思考一个哈希方法是容易的,难点在如何快速求子矩阵的 Hash 值。

具体来说,对于矩阵 A,二维哈希的前缀矩阵定义为:

Ii,j=k=1i(t=1jAk,j×base1jt)×base2ik=k=1it=1jAk,j×base1jt×base2ik

则其子矩阵 Aa..b,c..d 的哈希值为

Ia..b,c..d=Ib,dIb,c×base1cd+1Ia,d×base2ba+1+Ia,c×base1cd+1base2ba+1

posted @   weilycoder  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示