KMP string matching algorithm

给定两个串A,B

A = xyxxyxyxyyxyxyxyyxyxyxx

B = xyxyyxyxyxx

要求B是否为A的子串

一个最简单的想法就是从A的第一个字符开始跟B串匹配,如果匹配失败就从A的第二个字符开始跟B匹配,以此类推,直到成功,这种算法的复杂度是O(m*n)

KMP算法的原理比较复杂,我这里不说明了,直接说怎么用。

首先需要对B串构造一张NEXT表,

12 3 4 5 67 8 9 10 11

b xy x x y xy x x

next -10 0 12 0 1 23 4 3

这个表的构造方法如下

1. next[1] = -1 next[2] = 0

2. 对于next[i],

如果b[i-1] == b[next[i-1]+1],则next[i] = next[i-1]+1

如果b[i-1] != b[next[i-1]+1],考察是否有b[i-1] == b[next[next[i-1]+1]+1],若有则next[i] = next[next[i-1]+1]+1

以上情况依此类推,直到b[next[...]+1] = b[1] !=b[i-1],则next[i] = 0

接下来,怎么用这张表来查找子串呢

A: xyxxyxyxyyxyxyxyyxyxyxx

B: xyxy

开始两个子串头跟头对齐,一个个匹配下去直到第一个不匹配的字符。这里A的第四个是x而B的第四个是y。

接下来我们要保持A不动,向右移动B。KMP算法主要就是告诉我们移动多少格。

算法流程:

循环1次

发现不匹配的字符

B的不匹配的字符(y)对应的next[i]+1位置(2号位的y)跟A的不匹配字符(x)的位置对齐

A: xyxxyxyxyyxyxyxyyxyxyxx

B:     xy

循环2次

发现不匹配的字符

B的不匹配的字符(y)对应的next[i]+1位置(1号位的x)跟A的不匹配字符(x)的位置对齐

A: xyxxyxyxyyxyxyxyyxyxyxx

B:       xyxyy

循环3次

发现不匹配的字符

B的不匹配的字符(y)对应的next[i]+1位置(3号位的x)跟A的不匹配字符(x)的位置对齐

A: xyxxyxyxyyxyxyxyyxyxyxx

B:           xyxyyxyxyxx

循环4次

发现不匹配的字符

B的不匹配的字符(x)对应的next[i]+1位置(4号位的)跟A的不匹配字符(y)的位置对齐

A: xyxxyxyxyyxyxyxyyxyxyxx

B:                xyxyyxyxyxx


至此,在A中找到B的子串。

Algorithm String_Match(A,n,B,m)
Input: A (a string of size n), B (a string of size m), and assume that next has been computed
Output: Start (the first index such that B is a substring of A starting at A[start]
begin
    j:=1; i:=1;
    Start:=0;
    while Start=0 and i<=n do
        if B[j]=A[i] then
            j:=j+1; i:=i+1<span style="white-space:pre">	</span>//匹配相同的字符
        else<span style="white-space:pre">	</span>//发现不匹配的字符
            j:=next[j]+1;<span style="white-space:pre">	</span>//B的不匹配的字符对应的next[i]+1位置跟A的不匹配字符的位置对齐
            if j=0 then<span style="white-space:pre">	</span>//若next[i]+1 == 0,则B整体右移一格
                j:=1; i:=i+1;
        if j=m+1 then Start:=i-m
end






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值