KMP匹配算法复习。。
来源:互联网 发布:宝宝网络语言什么意思 编辑:程序博客网 时间:2024/06/05 18:41
KMP算法(Knuth–Morris–Pratt Algorithm),Knuth就是高德纳。
KMP算法是从朴素匹配算法改进而来:就是穷搜匹配。
朴素匹配算法:
原串:ABCDE 模式串:ACD
1. 将原串和模式串左对齐,然后一位一位比较,直到有一个字符不匹配
2. 发现第二位的B和C不匹配,模式串右移一位
3. 重复这个流程,直到找到完全匹配的子串或者匹配失败。
朴素匹配算法的不足:
就是不能够很直观的进行有移动的大跨步,也就是明明是不匹配的,但是不能跳过去,不够聪明。
例子:ABCDEABCDF 和 ABCDF。遇到E和F时候冲突,
此时明显人能直到应该直接调到E后面的A开始啊。
那是不是跳过的长度就是前面相同部分的长度呢?
其实不是这样的。
原串为ABCDABCDABF,模式串为ABCDABF,直接跳过相同部分就会遗漏匹配的串,所以跳过的长度并不是前面完全匹配的部分
那是不是跳过的长度如何定下来?
其实就是人之所以强大是可以马上发现下一个匹配开始的位置,比如模式串是A开头,那么匹配串肯定每次都是找到原串下一个A开始的继续匹配。机器不知道下一个究竟在哪,怎么跳过去合适。
也就是机器怎么靠近人的眼睛呢。直接发现下一个合理的开始位置呢,也就是如何跳到那个合理位置呢?这就是KMP算法解决的.
KMP算法
KMP算法需要对模式串进行预处理。
把可以跳过的长度一般存储在模式串的partial match table中。
例如:ABCDABF的partial match table如下:
可以跳过的长度 = 当前模式串已匹配长度 - 模式串最后一个字母在partial match table中的值。例如:
当发现C和F不匹配时,根据公式,当前已匹配串ABCDAB长度为6, 最后一个字母B在partial match table中的对应值为2,所以可以跳过的长度 = 6 - 2 = 4,即:
【partial match table是如何构建的?】
每个位置i记录的其实就是从0到i的子串中,同时出现在子串前缀和后缀中的最大长度。还是以上面那个例子为例:
- A没有前缀或后缀,所以长度为0
- AB前缀为A,后缀为B,没有相同部分,长度为0
- ABC前缀为A、AB,后缀为BC、C,没有相同部分,长度为0
- ABCD前缀为A、AB、ABC,后缀为BCD、CD、D,没有相同部分,长度为0
- ABCDA前缀为A、AB、ABC、ABCD,后缀为BCDA、CDA、DA、A,相同部分为A,长度为1
- ABCDAB前缀为A、AB、ABC、ABCD、ABCDA,后缀为BCDAB、CDAB、DAB、AB、B,相同部分为AB,长度为2
- ABCDABF前缀为A、AB、ABC、ABCD、ABCDA、ABCDAB,后缀为BCDABF、BCDAB、CDAB、DAB、AB、B,没有相同部分,长度为0
demo
'''Knuth-Morris-Pratt algorithm'''def getPrefix(pattern): ''' @param pattern: pattern string. @return: prefix array. ''' length = len(pattern) prefix = [0] * length for i in range(1, length): k = prefix[i-1] while k > 0 and pattern[i] != pattern[k]: k = prefix[k-1] if pattern[i] == pattern[k]: prefix[i] = k + 1 return prefixdef KMP(src, pattern): prefix = getPrefix(pattern) print(prefix) i = j = 0 src_len = len(src) pattern_len = len(pattern) if src_len < pattern_len: return -1 while i < src_len: while src[i] == pattern[j]: if j == pattern_len - 1: return i - j else: i += 1 j += 1 if j > 0: j = prefix[j-1] else: i += 1 return -1src = 'bbc abcdab abcdabcdabde'pattern = input('pattern: ')#'abcdabd'#print(KMP(src, pattern))print(getPrefix(pattern))
【延展】
这类问题的思路是解决重复,有点像qucik sort消除逆序对。
- KMP匹配算法复习。。
- [复习]KMP 字符串匹配
- KMP算法复习
- KMP算法复习
- 【各种算法】【kmp】复习
- (笔试前复习)比KMP算法更简单更快的字符串匹配算法
- 模式匹配---KMP算法
- 模式匹配 KMP算法
- 模式匹配-KMP算法
- KMP 字符串匹配算法
- KMP模式匹配算法
- kmp字符串匹配算法
- kmp字符匹配算法
- kmp字符串匹配算法
- KMP字符串匹配算法
- KMP模式匹配算法
- 字符串匹配算法-kmp
- KMP匹配算法详解
- CodeForces 833B 详细题解(貌似是四边形优化)
- QGraphicsView框架容易忽视的坐标问题-“画布”QgraphicsScene到底放在了哪儿?
- 多校赛01
- 备忘录模式
- PhpStorm格式化快捷鍵
- KMP匹配算法复习。。
- python学习(三)之list和tuple
- UVALive 7525
- docker容器内通过supervisor来守护进程
- FreeRTOS系统配置
- struts2-值栈/ngol语句/s标签
- C++中重载和排序问题的简单写法
- mybatis-mybatis与spring整合的基本配置
- use c++ automatic configure RemoteX USB redirection via modify windows policy group