给定两个串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 y y 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