KMP算法的正确性证明及一个小优化
直接把作业帖上来是不是有点不太公道呀。。。
无所谓啦反正各位看着开心就行
KMP算法
对于模式串$P$,建立其前缀函数$ N$ ,其中$N [q] $ 表示在$P$中,以$q$位置为结束的可以匹配到前缀的最长后缀的长度(也可以理解为那个前缀的结束位置),在匹配中,若$P[i]$与$S[j]$失配,则令$i=N [i-1] +1$ ,否则$i=i+1,j=j+1$
现考虑如何构造$N$ ,设当前以计算出$N[1..i-1]$ ,则令$k=N[i-1]$ ,若 $P[k+1]=P[i]$,则令$N[i]=k+1$ ,否则令$k=N[k]$ 。重复上述过程,直至找到$N[i]$
可证该算法能在$\Theta(|P|) $ 的时间内构造出前缀函数$N$ ,在$\Theta (|S|)$ 的时间内完成匹配,总的时间复杂度为$\Theta(|S|+|P|)$
KMP算法的正确性证明
先证明匹配过程的正确性:
在过程中,若$P[1..q]$ 与$S[s+1...s+q]$ 匹配,而$P[q+1]$与$S[s+q+1]$ 失配,那么由$N$的定义可立即得出$P[1..N[q]]$ 与 $S[s+q-N[q]+1...s+q]$ 匹配,而$S[1...t]$与$S[s+q-t+1...s+q]$ 失配$(N[q]<t<q)$ ,即只需检验$P[N[q]+1]$ 与$S[s+q+1]$ 的匹配情况即可,匹配过程的正确性即可得证。
接下来证明前缀函数$N$计算的正确性:
令$N^*[q]= \{N[q],N^{(2)}[q],…,N^{(t)}[q]\}$ 其中$N^{(t)}[q]=N^{(t-1)}[q],N^{(0)}[q]=N[q]$ ,那么$N^*[q]$ 为以q位置为结束的可以匹配到前缀的后缀的所有长度(即匹配到所有前缀的位置),同时有$N[q]-1\in N^*[q-1]$ ,因此只需从大到小枚举$N^*[q-1]$ 中的元素并通过判断即可得出$N[q]$ 。
KMP算法的时间复杂度证明
在匹配时:$i,j$增长了$|S|$ ,而在$i=N[i-1]+1$ 中,$i$ 至少减少1,即该语句至多执行了$|S|$次,因此时间复杂度为$\Theta(|S|)$。
构造前缀函数$N$ 时: 我们考虑k的变化,我们可以得到,在每次$k=N[k]$ 中,$k$ 至少减少1,又因为$k$随$i$增加了$|P|$次,即该语句至多执行$|P|$ 次,因此时间复杂度为$\Theta(|P|)$ 。
因此总的时间复杂度为$\Theta(|S|+|P|)$ 。
KMP算法的优化
我们希望通过优化,为了减少失配的概率,因此提出如下改进:
在构造$N'$数组时,当$P[k+1]=P[i]$ 时,若$P[i+1]=P[k+2]$ 则$N'[i]=k+1$ 否则$N'[i]=N'[k+1]$ 。
该优化的正确性证明
在匹配时,我们发现,若$P[q+1]$ 与$S[s+q+1]$失配,同时$P[q+1]=P[N^{(t)}[q]+1]$ ,则$P[N^{(t)}[q]+1]$一定与$S[s+q+1]$ 失配,因此若$P[N[q]+1]=P[q+1]$ ,则该比较一定失配,无需考虑。
在该优化中,由该函数的递归求法可得,$N'[q]=max\{N^*[q]且P[q+1]\neq P[N^{(t)}[q]+1]\}$ ,因此$N'[q]$ 依旧能枚举完所有可能匹配的前缀,同时减少失配概率。
该优化对算法空间与时间复杂度的影响
由于该优化只是改变了N数组的构造方法,因此对空间复杂度无影响。
时间复杂度的证明同KMP的证明,可得对最坏情况下的时间复杂度无影响
由于该算法避免了出现$P[N[q]+1]=P[q+1]$的情况,因此对于有较多重复子串的模式串有较好的优化效果(如aaaab,abcabcabcd)
KMP算法的正确性证明及一个小优化的更多相关文章
- KMP算法Next()函数的一个应用
转载:http://www.cnblogs.com/vongang/archive/2012/05/04/2483419.html 记一个KMP算法的应用,经典的KMP算法详解还是看这里 问题:给一个 ...
- kmp算法 汇总
来源:http://blog.csdn.net/qq_34494458/article/details/75253466 KMP算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,其 ...
- 真正理解KMP算法
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4403560.html 所谓KMP算法,就是判断一个模式串是否是一个字符串的子串,通常的算法当 ...
- KMP算法——从入门到懵逼到了解
本博文參考http://blog.csdn.net/v_july_v/article/details/7041827 关于其它字符串匹配算法见http://blog.csdn.net/WINCOL/a ...
- (原创)白话KMP算法详解
引子:BF暴力算法 KMP算法知名度相当高,燃鹅其理解难度以及代码实现对于初学数据结构和算法的同学并不友好,经过两天的总结,详细总结KMP算法如下: 初学串的模式匹配时,我们都会接触到,或者说应该能想 ...
- KMP算法的改进
KMP算法的改进 KMP算法已经在极大程度上提高了子符串的匹配效率,但是仍然有改进的余地. 1. 引入的情景 下面我们就其中的一种情况进行分析: 主串T为"aaaabcde-" 子 ...
- KMP算法解析(转自图灵社区)
KMP算法是一个很精妙的字符串算法,个人认为这个算法十分符合编程美学:十分简洁,而又极难理解.笔者算法学的很烂,所以接触到这个算法的时候也是一头雾水,去网上看各种帖子,发现写着各种KMP算法详解的转载 ...
- BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法
标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...
- 串的模式之kmp算法实践题
给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出.如果找不到,则输出“Not ...
随机推荐
- Tsinsen-A1491 家族【并查集】
问题描述 阿狸和桃子养了n个小阿狸, 小阿狸们每天都在一起玩的很开心. 作为工程师的阿狸在对小阿狸们之间的关系进行研究以后发现了小阿狸的人际关系由某种神奇的相互作用决定, 阿狸称之为“键”. 每个键有 ...
- UILabel常用属性小结
标签常用的属性: (1)frame属性:设置标签的位置与大小. frame = CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat heig ...
- matlab取模与取余
mod函数采用floor,rem函数采用fix函数.那么什么是floor和fix? fix(x):截尾取整.如: >> fix([3.4 , -3.4]) ans = 3 -3 floor ...
- MongoDB和MySQL的区别
http://www.cnblogs.com/caihuafeng/p/5494336.html MongoDB(文档型数据库):提供可扩展的高性能数据存储 一. 1.基于分布式文件存储 2.高负载情 ...
- 两台机子的repcached Memcache 的安装与实验
安装memcached前先要确定系统是否安装了gcc: 1.解压安装包: tar -zxf memcached-1.2.8-repcached-2.2.tar.gz 2.编译: 系统应安装了libev ...
- ServiceStack.Redis 使用链接池方法
PooledRedisClientManager 1.RedisManage.cs public static class RedisManager { private static PooledRe ...
- Java数据结构整理(一)
ava数据结构内容整理关键字: 数据结构 Collection:List.SetMap:HashMap.HashTable如何在它们之间选择一.Array , ArraysJava所有“存储及随机访问 ...
- DataTable.DataRow的复制
经常遇到这种错误,“此行已属于另一个表”的错误,导致这个错误的语句如下: dtPriceTable.Rows.InsertAt(aDataRow,i); 或者 dtPriceTable.Rows.Ad ...
- PHP检测获取内存信息
PHP也可以检测获取到Windows的内存信息,而且代码还挺简单,无意发现的,觉得以后能用上,在此与大家分享. 本代码将得到总内存.初始使用等内存信息: <?php echo "初始: ...
- Win10還原成最乾淨的狀態 不必重灌
系統不穩定時我們想到的第一個選擇就是重灌,如果你的作業系統是win10將會有另外一個新選擇,就是透過程式進行還原,讓你的電腦回到剛安裝時的清爽. 工具資訊 [軟體名稱]微軟 Refresh Windo ...