匹配——rabin_karp是怎么滚动的?

接前面

匹配——散列法里面只说前一个字符乘以128再对72057594037927931求模,答案乘以128加后一个字符再对72057594037927931求模。对应代码:

hash_s = (DOMAIN * hash_s + ord(s[i])) % PRIME

用例

还是用书上这个例子

>>>rabin_karp_matching('aabcbabcaabcaababc','abcaababc')
9
>>> 

在这里插入图片描述

公式

h a s h ( l e n t ) = ( s [ 0 ] ∗ D O M A I N L − 1 + s [ 1 ] ∗ D O M A I N L − 2 + s [ 2 ] ∗ D O M A I N L − 3 + . . . + s [ L − 2 ] ∗ D O M A I N 1 + s [ L − 1 ] ∗ D O M A I N 0 ) m o d P R I M E hash(len_t) = (s[0]*DOMAIN^{L-1} + s[1]*DOMAIN^{L-2} + s[2]*DOMAIN^{L-3} + ...+ s[L-2]*DOMAIN^1 + s[L-1]*DOMAIN^0 ) mod PRIME hash(lent)=(s[0]DOMAINL1+s[1]DOMAINL2+s[2]DOMAINL3+...+s[L2]DOMAIN1+s[L1]DOMAIN0)modPRIME
从hash_s打印的结果看,第一次是97,第二次12513,第三次1601762到7,8位的时候就是个17位的数了,跟公式应该对得上的。

滚动

代码只有三行,是怎么就去掉了第一个值out_digit的影响,再右移添加in_digit,完成一个循环的计算?

        val = (old_val - out_digit * last_pos + DOMAIN*PRIME) % PRIME
        val = (val * DOMAIN) % PRIME 
        return (val + in_digit) % PRIME

参数里last_pos是干什么的?old_val是前一次的散列值。

last_pos

last_pos = pow(DOMAIN, len_t -1) % PRIME #计算中没有变的。他写成算式是 D O M A I N L − 1 DOMAIN^{L-1} DOMAINL1, 前面公式里第一个s[0]乘以的值,即 s [ 0 ] ∗ D O M A I N L − 1 s[0]*DOMAIN^{L-1} s[0]DOMAINL1.只有一行一行看代码了。

第三行

return (val + in_digit) % PRIME

跟接前面那一行很像,但他是DOMAIN * hash_s加上新值再对PRIME求模。val可以变成这样的行式吗?

第二行

 val = (val * DOMAIN) % PRIME 

他多求了一次模,为什么要多求模?没事,不明白就先注释掉,两行变一行写成

return (val * DOMAIN + in_digit) % PRIME

打印的结果也是9,那第一行就是去掉第一个值out_digit的影响吗?

第一行

val = (old_val - out_digit * last_pos + DOMAIN*PRIME) % PRIME

按前面的公式来说减掉out_digit * last_pos,即 s [ 0 ] ∗ D O M A I N L − 1 s[0]*DOMAIN^{L-1} s[0]DOMAINL1.这里为什么多了个DOMAIN*PRIME。不明白的就去掉。

    def roll_hash(old_val, out_digit, in_digit, last_pos):
        #val = (old_val - out_digit * last_pos + DOMAIN*PRIME) % PRIME#去掉out的值
        val = (old_val - out_digit * last_pos) % PRIME#去掉out的值
        #val = (val * DOMAIN) % PRIME
        #return (val + in_digit) % PRIME
        return (val * DOMAIN + in_digit) % PRIME

这样打印的也是9,都有点不敢相信,字符前面加66也打印11了。

>>> rabin_karp_matching('aabcbabcaabcaababc','abcaababc')
9
>>> rabin_karp_matching('66aabcbabcaabcaababc','abcaababc')
11
>>> 

证明

看了很多网上的证明,也没怎么明白,只能理解到前面的第一个公式。求模不影响四则运算吗,
求模怎么影响四则运算的?把17位的质数改成101,DOMAIN也改成2,证明还是打印的11

   PRIME=101#72057594037927931 #17位
   DOMAIN=2#128

后话

求模

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值