已知字符串s为“abaabaabacacaabaabcc”,模式串T为“abaabc”。采用KMP算法进行匹配,第一次出现“失配”(s[i]≠t[j])时,i=j=5,则下次开始匹配时i和j的值分别是( )
A.i=1,j=0
B.i=5,j=0
C.i=5,j=2
D.i=6,j=2
解这道题前,首先要了解什么是KMP算法?
- KMP算法是三位学者提出来的,全称是克努特D.E.Knuth—莫里斯J.H.Morris—普拉特V.R.Pratt操作,是一种根据BF算法改进的字符串的模式匹配算法。
- 模式匹配就是在主串中寻找一个给定的模式,返回主串和模式串匹配的第一个子串的首字符位置。通常主串比较大,而模式串则比较短小。
- 所以如果要了解什么是KMP算法,需要先了解什么是BF算法。
- BF算法(Brute Force算法)
- 而KMP算法在上述情况下,通过一个本身包含了模式串的局部匹配信息的next()函数,利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的,即主串位置不需要回退【或者理解为求得模式的特征向量之后,在每次匹配过程中发生某次失配时,不再单纯地把模式后移一位,而是根据当前字符的特征数来决定模式右移的位数(右移的距离是由模式串T本身决定的,即T的子串t[0...j-1]中的前缀串和后缀串相等的最长长度)】,这样就可以大大提高效率,这就是KMP算法。
回到题目:
已知字符串s为“abaabaabacacaabaabcc”,模式串T为“abaabc”。采用KMP算法进行匹配,第一次出现“失配”(s[i]≠t[j])时,i=j=5,则下次开始匹配时i和j的值分别是( )
A.i=1,j=0
B.i=5,j=0
C.i=5,j=2
D.i=6,j=2
根据上面讲到的知识:
KMP算法在发生某次失配(s[i]≠t[j])时,i会保持不变,而对于j,
KMP算法由于不再单纯地把模式后移一位,而是根据当前字符的特征数来决定模式右移的位数(右移的距离是由模式串T本身决定的,即T的子串t[0...j-1]中的前缀串和后缀串相等的最长长度),故j会根据上面的方法回退到next的位置并重新比较
本题中讲到字符串s为“abaabaabacacaabaabcc”,模式串T为“abaabc”,
又因为模式串T的子串称为子串t,
第一次失配时i=5,则子串t为“abaab”,
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
主串s “abaabaabacacaabaabcc” | a | b | a | a | b | a | ... |
【此处模式串T与主串s发生失配】 | |||||||
模式串T “abaabc” | a | b | a | a | b | c | |
子串t | a | b | a | a | b |
故在这个子串t里面即“abaab”这5个字符中相等且最长的前后缀为“ab”,即“abaab”,
即T的子串t[0...j-1]中的前缀串和后缀串相等的最长长度j=2,代表右移了2位,
故下次开始匹配时i不变为5,j为2,
故选C。