基本思想
目标(target):主串
模式(pattern):要在主串中寻找的子串
从左往右将模式的每个字符和对应位置的目标字符比较,在模式的第j位不匹配称为失配,则模式中失配位置之前的子串P0P1...Pj−1全部匹配上:
T:T0T1...TsTs+1...Ts+j−1Ts+j...Tn−1
P: P0P1 ...Pj−1 Pj...Pm
若此时在模式P中存在最大的k,使得P0...Pk=Pj−k−1...Pj−1,即模式P中有首尾重叠的部分,则下次比较可以将模式P向后移动j−k−1位:
T:T0T1...TsTs+1...Ts+j−k−1...Ts+j−1Ts+j...Tn−1
P: P0P1 ...Pj−k−1 ...Pj−1 Pj...Pm
P: P0 ...Pk Pk+1...Pj...Pm
由k的极大性可以保证将模式P向后移动少于j−k−1位不会匹配,因为若匹配上了,意味着有更大的k满足P0...Pk=Pj−k−1...Pj−1,从而破坏了k的极大性。
由上述分析可知对于某个j,k的取值只和模式P有关,从而对于固定的P,k是j的函数,记k=next[j],next[j]表达式,后续给出其求法:
next[j]=⎩⎪⎨⎪⎧−1k+10j=0k为满足0⩽k<j−1且P0...Pk=Pj−k−1...Pj−1的最大整数else
算法流程
start:从目标T的start(从0开始)处开始匹配模式P
len_match:P中已经匹配上的长度,也即P进行匹配的起始位置,初始为0
length_target:T的长度
length_pattern:P的长度
next:数组,表示P的next向量
1、若length_pattern+start>length_target则返回-1(表示匹配失败)
2、从左到右逐一比较模式Plen_match...Pm和目标的字符,若全部匹配则返回目标匹配的起始位置start;否则假设直到Pj不匹配:
若next[j]=−1(即j=0,第一个字符就匹配失败),则start自增,转1;
否则将start增至P与原来的P有next[j]个重合,根据next[j]定义,重合部分T和P全部匹配,从而只需要从下一个位置,即next[j]开始继续比较,,故令len_match=next[j],转1。
例如T=acabaabaabcacaabc,P=abaabcac时的匹配过程如下:

next向量计算
由定义next[0]=−1,表示P0失配时start需要向后移动1位重新开始匹配。
next[1]=0(定义中的else情况)。
对于失配位置j,next[j]的意义为P0P1...Pj−1首尾能重叠的最大长度,即满足P0...Pk=Pj−k−1...Pj−1的最大的k+1,0⩽k<j−1,若不存在重叠部分即为0。
为了求next[j],可以考虑其与next[j−1]的关系。
1、设k=next[j−1],j>1,则由next[j−1]的意义有P0...Pk−1=Pj−k−1...Pj−2:
P0P1 ...Pj−k−1...Pj−2Pj−1Pj...Pm
P0 ...Pk−1Pk ...Pj...Pm
2、若Pk=Pj−1,则有P0...Pk=Pj−k−1...Pj−1,且此k具有极大性,从而next[j]=next[j−1],返回。
3、若Pk=Pj−1,则需要寻找最大的k′使得P0...Pk′=Pj−k′−1...Pj−1成立:
P0P1 ...Pj−k−1...Pj−k′−1...Pj−2Pj−1Pj...Pm
P0 .................Pk−1Pk ...Pj...Pm
P0 ...Pk′−1Pk′ ...Pm
于是有P0...Pk′−1=Pk−k′...Pk−1,即k′=next[k]。
4、若k′=−1,则next[j]=0,否则令k=k′,转2.
例如P=abaabcac的next向量计算过程如下:

代码
代码在这里
图片来源
例子的图片来自清华大学殷人昆和王宏的数据结构电子教案。