利用跳转表实现字符串匹配的算法如下:
unsigned int KMP(const char* text, size_t text_length, const char* pattern, size_t pattern_length, unsigned int* matches) { unsigned int i, j, n; unsigned int next[pattern_length + 2]; BuildNext(pattern, pattern_length, next); i = 0; j = 1; n = 0; while(pattern_length + 1 - j <= text_length - i) { if(text[i] == pattern[j - 1]) { ++i; ++j; //发现匹配结果,将匹配子串的位置,加入结果 if(j == pattern_length + 1) { matches[n++] = i - pattern_length; j = next[j]; } } else { j = next[j]; if(j == 0) { ++i; ++j; } } } //返回发现的匹配数 return n; }该算法在原有基础上进行了扩展,在原模式串末尾加入了一个“空字符”,“空字符”不等于任何的可输入字符,当目标串匹配至“空字符”时,说明已经在目标字符串中发现了模式,将模式串在目标串中的位置,加入matchs[]数组中,同时判定为匹配失败,并根据“空字符”的next,跳转到适当位置,这样算法就可以识别出字符串中所有的匹配子串。
最后,对kmp算法的正确性做一简要说明,还是以上文的模式串pattern和目标串target为例,假设已经匹配到第3部的位置,且在target[13]处发现匹配失败,我们如何决定模式串的滑动步数,来保证既要忽略不必要的多余比较,又不漏过可能的匹配呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
target b a b c b a b c a b c a a b c a b c a b c a c a b c
pattern a b c a b c a c a b
对于例子中的情况,显然向后移动多于3个字符有可能会漏过target[9...18]这样的的可能匹配。但是为什么向后移动1个或者2个字符是不必要的多余比较呢?当target[13]与pattern[8]匹配失败时,同时也意味着,target[6...12]
= pattern[1...7],而next[8]=5,意味着,pattern[1...4] = pattern[4...7],pattern[1...5]
!= pattern[3...7],pattern[1...6]
!= pattern[2...7],。如果我们将模式串后移1个字符,使pattern[7]与target[13]对齐,此时target[7...12]相当于pattern[2...7],且target[7...12]与pattern[1..6]逐个对应,而我们已经知道pattern[1...6]
!= pattern[2...7]。所以不管target[13]是否等于pattern[7],此次比较都必然失败。同理向前移动2个字符也是多余的比较。由此我们知道当在pattern[j]处发生匹配失败时,将当前输入字符与pattern[j]和pattern[next[j]]之间的任何一个字符对齐执行的匹配尝试都是必然失败的。这就说明,在模式串从目标串头移动到目标串末尾的过程中,除了跳过了必然失败的情况之外,没有漏掉任何一个可能匹配,所以kmp算法的正确性是有保证的。
后记:

以上就是关于kmp算法的全部内容,相信你一定会非常满意。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shenmilingyu/article-3601-3.html
亏了再圈
台湾自古属中国
唱歌好听
它已超出了双边或多边的范畴