字符串比较算法(i是主串的比较指针,j是子串比较指针)

传统算法
逐个比较,遇到不同的字符回溯 i 。存在 i 的回溯问题,如上图所示
KMP算法
改进了传统的算法:每当一趟匹配过程中出现字符比较不等时,不需要回溯i指针,而是利用“部分匹配”的结果将模式向右“滑动”尽可能远的距离后,继续比较。
如图所示,从传统比较的第三趟部分可知,主串中第4、5、6个字符必然是 b c a(即模式串中第2、3、4个字符)所以可以向后滑动3个位置后继续比较,即进行i=7,j=2时的字符串比较即可。同理,在第一趟匹配出现字符不等时,仅需要将模式向右移动两个字符的位置继续进行i=3,j=1时的比较。
现在讨论一般情况。假设
+ 主串为”s1 s2 … sn”
+ 模式串为”p1 p2 … pn”
为了改进上述的传统算法,我们需要知道“当主串中第 i 个字符与模式串中的 第j 个字符“失配”时,主串中的第i个字符(i指针不回溯)应该与模式串中的那个字符进行比较?”
假设此时应该与第 k(k<j) 个字符进行比较,则模式串中的前 k-1 个字符与子串必须满足下列关系(1)

从已经得到的部分匹配结果可知(2)
由(1)和(2)可推出(3)

主串 a b a b c a b c a c b a b
模式串 a b c a c
如上:当i=7,j=5时出现了失配,我们分析
1)当k=2时
公式(1)满足 p1 = p6 即 a = a
公式(2)满足 p4 = s6 即 a = a
即 p1=p4
2)当k=3时
公式(1)满足 p1 p2 = s5 s6 但是a b != c a
公式(2)满足 p3 p4 = s5 s6 即 c a = c a
即 p1p2 != p3p4
3)当k=4时
公式(1)满足 p1 p2 p3 = s4 s5 s6,但是 abc!=bca,所以k!=4
即 p1 p2 p3 != p2 p3 p4
要求k<j所以k的最大值为2
即 k=2,也就是当i=7,j=5时失配后,主串中i=7的位置的字符 b 应该与子串中的第 k(k=2)个字符 b进行比较。
由上可知,若模式串中存在满足式(3)的两个子串,则当匹配过程中,主串中第 i 个字符与模式串中第 j 个字符比较不等时,仅需要将模式串向右滑动到模式串中第 k 个字符去和主串中第 i 个字符对齐,此时,模式串中前k-1个字符的子串必满足公式(1)。由此,匹配仅需从模式串中第 k 个字符与主串中第 i 个字符比较起继续进行。
若另next[j]=k,则 next[j]表明当模式中第j个字符与主串中相应的字符“失配”时,在模式找那个需要重新和主串中该字符进行比较的字符位置。由此可引出模式串的next函数的定义:

即 next[j]=k 为 next[5] = 2
由此可推出下列模式串的next函数值:

从上述的分析可知,模式串的next数组取决于模式串本身,和相匹配的的主串没有关系.
由定义可知 next[1]=0
设 next[j] = k,表明在模式串中存在下列关系,其中 1<k<j:

此时 next[j+1] = ?可能存在两种情况:
+ 若 pk = pj,则表示模式串中‘p1 … p’ = ‘pj-k+1 … pj’,此时 next[j+1] = next[j]+1;
+ 若 pk != pj ,则表示模式串中‘p1 … pk’ != ‘pj-k+1 … pj’,此时可以把求next函数值的问题看成是一个模式匹配的问题,整个模式串既是主串又是模式串,而当前的匹配过程中,已有 ‘p1 … pk-1’ = ‘pj-k+1 … pj-1’,则当pj!=pk时应将模式串向右滑动至以模式中的第 next[k]个字符串中的第j个字符相比较,若next[k] = k’,且 pj = pk’,则说明在主串中第 j+1 个字符之前存在一个长度为 k’(即 next[k])的最长子串,和模式串中从首子符长度为 k’ 的子串相等,即满足(4)

这就是说 next[j+1] = k’+1 即* next[j+1] = next[k]+1*
同理,如 pj != pk’,则将模式继续向右滑动直至将模式中第 next[k’]个字符和pj对齐,。。。,依次类推,知道 pj 和模式中某个字符匹配成功或者不存在任何 k’(1<k’<j)满足(4),则next[j+1]=1
例如,图中已求得前6个字符的next函数值,现求next[7],因为next[6]= 3,又有 p6!=p3,则比较p6和p1(因为next[3] = 1),这相当于将子串模式向右滑动。由于 p6!=p1,而且 next[1] =0,所以next[7]=1,而因为 p1 = p7,所以 next[8] = next[7]+1 = 2
测试用例:
abaca:01121
ababaaababaa:011234223456