BDKRHash详解

公式证明

在之前的某一篇博客中我写了,关于BDKRHash的简短的介绍,还没有对其公式和原理进行阐述,实在是罪过罪过。


 

首先给出BDKRHash的公式

1.$$hashvalue[i]=(hashvalue[i-1]*seed+str[i]-'a'+1)%P$$(也可以用ASCLL码值,但容易爆)

2.$$Hashvalue[l……r]=(hashvalue[r]-hashvlaue[l-1]*seed^{r-l+1})%P$$(注意第一个Hashvalue与hashvalue不同)

第一个公式不需要证明,这是BDKRHash的定义式,意思就是:发明BDKRHash的人就是这么写的。这个东西只有用记忆的方法来掌握,如果要深究其原理,太过深奥,蒟蒻我不懂。

接下来我们针对第二个公式进行证明: Hashvalue代表的是从l到r这个区间的字串的hash值,hashvalue代表从第1个开始到第i个的hash值。下面开始证明

先看第一个公式

$$hashvalue[i]=(hashvalue[i-1]*seed+str[i]-'a'+1)%P$$

我们把每一项展开可以得到(为方便表达,接下来hashvalue简写为hash,str[i]-'a'+1简写为str[i])

$$hash[0]=0$$

$$hash[1]=str[1]%P$$

$$hash[2]=hash[1]*seed+str[2]$$

$$hash[3]=hash[2]*seed+str[3]$$

$$hash[i]=hash[i-1]*seed+str[i]$$

$$hash[n]=hash[n-1]*seed+str[n]$$

看出一些规律了吗?如果没有,我们再把每一项中的hash[i]*seed展开:

$$hash[2]=(str[1])*seed+str[2]$$

$$hash[3]=(str[1]*seed+str[2])*seed+str[3]$$

$$hash[4]=((str[1]*seed+str[2])*seed+str[3])*seed+str[4]$$

$$hash[i]=(((str[1]*seed+str[2])*seed+str[3])*seed······)*seed+str[i-1])+str[i]$$

再把括号全部展开: 

$$hash[i]=str[1]*seed^{i-1}+str[2]*seed^{i-2}+······+str[i]*seed^{i-i=0}$$

到这里我们已经大致得到了BDKRHash的最终表达式,通过对这个式子进行变形,就可以得到第二个公式:

$$令l=1,则r=r-l+1$$

$$hash[l······r]=hash[1······r-l+1]=str[1]*seed^{r-l}+str[2]*seed^{r-l-1}+······+str[r-l+1]*seed$$

把1还原为l

$$hash[l······r]=str[l]*seed^{r-l}+str[l+1]*seed^{r-l-1}+······+str[r]*seed$$

写到这里,可能大家都已经明白了。

$$hash[1······l-1]=str[1]*seed^{l-2}+str[2]*seed^{l-3}+······+str[l-1]*seed\dashrightarrow①$$

$$hash[1······r]=str[1]*seed^{r-1}+str[2]*seed^{r-2}+······+str[r]*seed\dashrightarrow②$$

$$②-①*seed^{r-l+1}$$

得到 $$hash[1······r]=hash[1······l-1]*seed^{r-l+1}+str[l]*seed^{r-l}+str[l+1]*seed^{r-l-1}+······+str[r]*seed$$

$$hash[l······r]=str[l]*seed^{r-l}+str[l+1]*seed^{r-l-1}+······+str[r]*seed得$$ 

$$hash[l······r]=hash[1······r]-hash[1······l-1]*seed^{r-l+1}$$

又Hashvalue代表的是从l到r这个区间的字串的hash值,hashvalue代表从第1个开始到第i个的hash值。 

$$Hashvalue[l……r]=(hashvalue[r]-hashvlaue[l-1]*seed^{r-l+1})%P$$

完结。 如果不懂,可以自己按着推一遍。


 

BDKRHash判断回文字符串:

主要是通过下面这个式子判断。

$$hash[i]=str[1]*seed^{i-1}+str[2]*seed^{i-2}+······+str[i]*seed$$

观察之后不难发现,hash值是可以逆向来求的,即:

int seed=1;
for(int i=n;i>=1;i--)
{
    hash[i]=hash[i+1]+str[i]*seed;
    seed*=107;
}

 

 

 

所以我们只用循环一遍就可以得到,1到i长度的字符串是不是回文字符串。

转载于:https://www.cnblogs.com/Y-sofun/p/7576610.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值