滚动哈希(Rabin-Karp算法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37846371/article/details/72854890

滚动哈希: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;
}


阅读更多
换一批

没有更多推荐了,返回首页