字符串匹配rk算法c语言,字符串匹配问题(BF&RK算法)

1. 题目

有一个主串S={a,b,c,a,c,a,b,d,c},模式串T={a,b,d},请找出模式串在主串中第一次出现的位置

提示:不需要考虑字符串大小写问题,字符均为小写字母

2. BF算法

BF算法,又称爆发匹配算法,简单来说,就是将模式串一个一个字符与主串进行对比,直到模式串中所有的字符匹配成功。

解法思路:

1、 分别利用计数指针i和j,指示主串S和模式T中当前正待比较的字符位置,i初值为pos,j的初值为1;

2、 如果2个串均为比较到串尾,即i和j均小于等于S和T的长度时, 则循环执行以下的操作:

S[i]和T[j]比较,若相等,则i 和 j分别指示串中下一个位置,继续比较后续的字符;

若不相等,指针后退重新开始匹配. 从主串的下一个字符串(i = i – j + 2)起再重新和模式第一个字符(j = 1)比较;

3、 如果j > T.length, 说明模式T中的每个字符串依次和主串S找中的一个连续字符序列相等,则匹配成功,返回和模式T中第一个字符的字符在主串S中的序号(i-T.length);否则匹配失败,返回0;

9f5ca2b6d175c48db11bdf7cbdda1c8e.png

辅助部分

核心部分

3. RK算法

相对来说,比较字母总是不如比较数字大小来的简单,那么我们是否可以将字符通过什么方式来计算出对应的数字结果呢?

我们的前辈,Rabin和Karp就很有想法的,通过设计一个哈希公式,利用字符串对应的哈希值来进行比较。即我们已知的模式串可以计算出它的哈希值,同时将主串拆分出与模式串相同长度的子串来计算哈希值,比较两个哈希值是否相等。

那么问题来了:如何将一个‘bcd’换算成一个哈希值?

通过ASCII表可以直到字母对应的ASCII值,‘a’ = 97。

字母一共有26位,我们可以设计一个26进制

bcb = ('b'-'a')*26^2 + ('c'-'a')*26^1 + ('b'-'a')*26^0;

其中的2次方,也可以认为是模式串长度m减1得来的。

上边计算字符串的哈希值的逻辑假如理解的话,那我们可以再来想一个问题:主串拆分出来的,相邻两个子串,对应的哈希值计算公式是否有交集?是否可以通过前一个子串的哈希值,来求得下一个子串呢?

我们再来看看:

假如相邻的两个字符为’bcb’和’cba’,他们的哈希计算分别为

bcb = (‘b’-‘a’)*26^2 + ('c'-'a')*26^1 + ('b'-'a')*26^0;

cba = ('c'-'a')*26^2 + ('b'-'a')*26^1 + (‘a’-‘a’)*26^0;

可以看到,‘bcb‘减去了最高位的‘b’,同时后两位的多乘了一次26,然后再加上下一个字符串的最低位’a’,得到的结果就是‘cba’的哈希值。

最终的公式

St[i] = (St[i-1] - 26^(m-1)*(S[i]-'a')) * 26 + (S[i+m]-'a')

ps:St[i]为主串中当前子串的哈希值,St[i-1]为前一个子串的哈希值,m为模式串的长度

那么,两个字符串的哈希值相等,就表示两个字符串就一定相同吗?

答案是不一定的,所以我们还需要进一步进行验证,哈希值相等时,两个字符串是否真的匹配?

辅助部分

核心部分

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值