字符串匹配----哈希算法

寻找字符串S中字符串T出现的位置或次数的问题属于字符串匹配问题。我们接下来讨论中假设S的字符串长度为 n,T的长度为m。最朴素的想法是,枚举所有起始位置,再直接检查 是否匹配,复杂度为O(nm)的算法。还有几个为高效的算法。而在此我们只介绍实现起来较为容易,而在一些稍作变化的问题中同样适用,并且可以简单地推广到二维情况的哈希算法。
将哈希算法用于字符串匹配的原理非常简单。对于每个起始位置,我们不是O(m)地直接比较字符串是否匹配,而是O(l)地比较长度为m的字符串子串地哈希值与T地哈希值是否相等。虽然即使哈希值相等也未必相等,但如果哈希值是随机分布地话,不同的字符串哈希值相等的概率是很低的,可以当作这种情况不会发生。
但是,如果我们采用O(m)的算法计算长度为 m地字符串子串地哈希值的话,那复杂度还是O(nm)。这里我们要使用一个叫做滚动哈希的优化技巧。选取两个合适的互素常数b和h(l

#include<string>
#include<iostream>
using namespace std;
typedef unsigned long long ull;
const ull B = 100000007;//哈希的基数
//a 是否在 b中出现
bool contain(string a,string b){
    int al = a.length(),bl = b.length();
    if(al > bl)
        return false;

    //计算 B的 al次方 
    ull t = 1;
    for(int i=0;i<al;i++)
        t *= B;
    //计算 a和 b的长度为 al的前缀对应的哈希值
    ull ah = 0,bh = 0;
    for(int i=0;i<al;i++){
        ah = ah * B + a[i];
    } 
    for(int i=0;i<al;i++){
        bh = bh * B + b[i]; 
    }   

    //对 b不断右移一位,更新哈希值并判断
    for(int i=0;i + al <= bl;i++){
        if(ah == bh)
            return true;// b从位置 i开始长度为 al的字符串字串等于 a
        if(i + al < bl)
            bh = bh * B + b[i+al] - b[i] * t; 
    } 
    return false;
} 

当然不光是右移一位,对于左移一位、左端或右端加长一位或是缩短一位的情况,也能够进行类似处理。譬如说,假设要求S的后缀和T的前缀相等地最大长度,可以利用滚动哈希在O(n+m)的时间内高效地求得。

#include<string>
#include<iostream>
using namespace std;
typedef unsigned long long ull;
const ull B = 100000007;//哈希的基数

// a的后缀和 b的前缀相等的最大长度
int overlap(string a,string b){
    int al = a.length(),bl = b.length();
    int ans = 0;
    ull ah = 0,bh = 0,t = 1;
    for(int i=1;i<=min(al,bl);i++){
        ah = ah + a[al - i] * t;// a的长度为 i的后缀的哈希值
        bh = bh * B + b[i-1];// b的长度为 i的前缀的哈希值
        if(ah == bh)
            ans = i;
        t *= B; 
    } 
    return ans;
} 
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值