KMP算法 学习小记 发表于 2017-11-02 | 分类于 Demo KMP是一种字符串匹配算法,通过对模式字符串的处理,可以达到O(n+m)的时间复杂度 正文参考文章字符串匹配的KMP算法 简易的匹配算法123456789101112131415161718192021对于字符串匹配,一种显而易见的想法是[B]ABABCABCD[A]BCB[A]BABCABCD [A]BC开始尝试匹配下一位BA[B]ABCABCD A[B]CBAB[A]BCABCD AB[C]当检测到A,C不匹配则退回到主串匹配开始的下一位重新匹配BA[B]ABCABCD [A]BC这一过程称为'回溯'显然因为大量的回溯使得在最坏情况下时间复杂度达到了O(n*m) KMP算法123456789101112131415161718192021222324对于形如下的匹配BBC ABCDAB[ ]ABCDABCDABDE ABCDAB[D]基于一种事实,即我们已经知道已经成功匹配的部分是 ABCDAB,那么在BBC ABCDAB[ ]ABCDABCDABDE AB[C]DABD之前的部分都是冗余的,KMP算法通过对子串的特殊处理直接跳转到这一步,避免了回溯。构建一张表如下ABCDABD0000120其中A=1代表若字符'A'已经匹配,则新的匹配可以从子串中序号为1的字符'B'(从0开始计数)重新开始。B=2则表示由于'AB'已经匹配,子串开头的'AB'就不用再额外匹配了,即从'C'开始匹配。对于这张表的使用解读如下当匹配到BBC ABCDAB[ ]ABCDABCDABDE ABCDAB[D]因为前一个字符B=2,则可以直接跳转到BBC ABCDAB[ ]ABCDABCDABDE AB[C]DABD ‘表’的计算12345678以'ABCD[A]BD'中的'A'为例取出'ABCDA'计算前缀字符串['A', 'AB', 'ABC', 'ABCD']计算后缀字符串['BCDA', 'CDA', 'DA', 'A']找出其中相同的字符串'A'该字符串的长度为1若结果有多个,取长度最大的 Demo不想慢慢造轮子,就用python写了,能体现算法就好Orz 12345678910111213141516171819202122232425262728293031323334353637# -*- coding: utf-8 -*-s = 'BBC ABCDAB ABCDABCDABDE't = 'ABCDABD'def GetPat(s): r1 = [s[:i+1] for i in range(len(s)-1)] r2 = [s[i+1:] for i in range(len(s)-1)] return max([len(x) for x in r1 if x in r2] + [0])def GetAllPat(s): return [GetPat(s[:i+1]) for i in range(len(s))]def main(s, t): pat = GetAllPat(t) #print pat i = 0 j = 0 while i < len(s): while i < len(s) and j < len(t): if s[i] == t[j]: i += 1 j += 1 print i, j elif j == 0: i += 1 else: j = pat[j-1] if i == len(s): print 'traverse end.' break else: j = 0if __name__ == '__main__': main(s, t) 结语ps: 感冒貌似快好了(一感冒真的除了躺着什么都不想做…)