字符串Hash

字符串Hash引入

 下面介绍的字符串 H a s h Hash Hash函数把一个任意长度的字符串映射成一个非负整数,并且其冲突的概率几乎为0。
取一固定值 P P P,把字符串看作 P P P进制数,并分配一个大于 0 0 0的数值,代表每种字符。一般来说,我们分配的数值都远小于 P P P。例如,对于小写字符构成的字符串,可以令 a = 1 , b = 2 , . . . , z = 26 a=1,b=2,...,z=26 a=1,b=2,...,z=26取一固定值 M M M,求出该 P P P进制数对 M M M的余数,作为该字符串的 H a s h Hash Hash值。
一般来说,我们取 P = 13331 P=13331 P=13331,此时 H a s h Hash Hash值产生冲突的概率极低,只要 H a s h Hash Hash值相同,我们就可以认为原字符串是相等的。通常我们取 M = 2 64 M=2^{64} M=264,即直接使用 u n s i g n e d    l o n g    l o n g unsigned\;long\;long unsignedlonglong类型存储这个 H a s h Hash Hash值,在计算时不处理算术溢出问题,产生溢出时相当于自动对 2 64 2^{64} 264取模,这样可以避免低效的取模(mod)运算。
 除了极特殊的构造的阴间题目上,上诉 H a s h Hash Hash算法很难产生冲突,一般情况下上诉 H a s h Hash Hash算法完全可以出现在题目的标准解答中。(当然我们也可以多取一些 P P P M M M,多进行几次 H a s h Hash Hash函数的计算,如果仍然相同才认为两个字符串相同。)

字符串Hash的操作

 原理:对于字符串的各种操作,都可以直接对 P P P进制数进行算术运算反映到 H a s h Hash Hash值上。

 我们记字符串 S S S H a s h Hash Hash值为 H ( S ) H(S) H(S),那么在 S S S后拼接一个字符 c c c构成的新字符串 S + c S+c S+c H a s h Hash Hash值就是 H ( S + c ) = ( H ( S ) ∗ P + v a l ( c ) ) m o d P H(S+c)=(H(S)*P+val(c))mod P H(S+c)=(H(S)P+val(c))modP。是不是有点类似于数和数之间的拼接?

 如果我们知道字符串 S S S H a s h Hash Hash值为 H ( S ) H(S) H(S),字符串 S + T S+T S+T H a s h Hash Hash值为 H ( S + T ) H(S+T) H(S+T),那么字符串 T T T H a s h Hash Hash值就是 H ( T ) = ( H ( S + T ) − H ( S ) ∗ P l e n g t h ( T ) ) m o d M H(T)=(H(S+T)-H(S)*P^{length(T)}) mod M H(T)=(H(S+T)H(S)Plength(T))modM。这就相当于通过 P P P进制下在 S S S后面补 0 0 0的方式,把 S S S左移到与 S + T S+T S+T的左端对齐,然后两者相减就得到了 H ( T ) H(T) H(T)。(如下图说明)
在这里插入图片描述
 我们再看一下下图的例子
在这里插入图片描述

 根据上面两种操作,我们可以通过 O ( N ) O(N) O(N)的时间预处理字符串所有前缀 H a s h Hash Hash值,并在 O ( 1 ) O(1) O(1)的时间内查询它的任意子串的 H a s h Hash Hash值。

例题训练(持续更新中)

兔子与兔子 AcWing138

 题目分析:根据题意模拟字符串匹配即可,求出区间Hash值比大小。
 代码之后补上……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值