滚动哈希(Rabin-Karp算法)

滚动哈希:O(n+m)时间内完成字符串匹配;

实现:选取两个合适的互素常数b和h(l<b<h),假设字符串C=c1c2c3...cm,定义哈希函数:H(C)=(c1*b^(m-1)+c2*b^(m-2)+...+cm*b^0)mod h

其中b是基数,相当于把字符串看作b进制数。这样,字符串S=s1s2s3...sn从位置k+1开始长度为m的字符串子串S[k+1...k+m]的哈希值,就可以利用从位置k开始的字符串子串S[k...k+m-1]的哈希值,直接进行如下计算:H(S[k+1...k+m])=(H(S[k...k+m-1])* b - sk*b^m + s(k+m)) mod h

于是,只要不断这样计算开始位置右移一位后的字符串子串的哈希值,就可以在O(n)时间内得到所有位置对应的哈希值,从而可以在O(n+m)时间内完成字符串匹配。在实现时,可以用64位无符号整数计算哈希值,并取h等于2^64,通过自然溢出省去求模运算。


代码:

typedef unsigned long long ull;
const ull b=100000007;//哈希的基数;
//a是否在b中出现
bool contain(string C,string S)
{
     int m=C.length(),n=S.length();
     if(m>n)  return false;

     //计算b的m次方
     ull t=1;
     for(int i=0;i<m;i++)   t*=b;

     //计算C和S长度为m的前缀对应的哈希值
     ull Chash=0,Shash=0;
     for(int i=0;i<m;i++)   Chash=Chash*b+C[i];
     for(int i=0;i<m;i++)   Shash=Shash*b+S[i];

     //对S不断右移一位,更新哈希值并判断
     for(int i=0;i+m<=n;i++){
          if(Chash==Shash)  return true;//S从位置i开始长度为m的字符串子串等于C;
          if(i+m<n)  Shash=Shash*b-S[i]*t+S[i+m];
      }
      return false;
}


  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值