KMP算法,非常经典。现在只考虑一个问题,为什么原串的 originIndex 能跳跃?
现在准备两个串 origin 和 match ,长度分别是 N 和 M ,分别代表原串和匹配串。
有 next 数组,下标为 nextIndex 的值代表:match 串 nextIndex 之前(不包含)前缀后缀能匹配的最长长度。
假设现在 origin 的下标是 k , match 的下标是 0 ;进行匹配的结果是 match 匹配到 f 的时候,匹配失败。
设 n = next[f] ,那么根据 KMP 算法,跳跃的 originIndex 将会是 k+1,k+2 ~~ k+f-n-1
即下一次匹配 originIndex 将是 k+f-n 。下面是跳跃的证明,设 y=1,2 ~~ f-n-1
采用反证法进行证明。
假设存在这种情况:将 originIndex 移动到k+y的时候,匹配成功。
整理已知:
origin[k+index] == match[0+index] index=0,1 ~~ f-1
origin[k+y+index] == match[0+index] index=0,1 ~~ M-1
得到下面等式:
match[0] == origin[k+y+0] == origin[k+(y+0)] == match[y+0]
match[1] == origin[k+y+1] == origin[k+(y+1)] == match[y+1]
match[index] == origin[k+y+index] == origin[k+(y+index)] == match[y+index]
match[f-1-(y+1)] ==orgin[k+y+f-y-2] == origin[k+f-2] ==match[f-2]
match[f-1-(y)] == orgin[k+y+f-y-1] == origin[k+f-1] == match[f-1]
知道,match 现在有一个前缀 0 ~~ f-1-y,有一个后缀 y ~~ f-1 是完全匹配的。
而这个前缀后缀的长度是 f-y 且 n+1 <= f-y <= f-1,
即 nextIndex = f 时候,next[nextIndex] 的值是 f-y 大于原来的值 n ,在这里产生矛盾。
而当 y = f-n 时候,前后缀长度是 n,应该进行匹配判断。故 originIndex 移到 k+f-next[f]