直接把作业帖上来是不是有点不太公道呀。。。

无所谓啦反正各位看着开心就行

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算法的正确性证明及一个小优化的更多相关文章

  1. KMP算法Next()函数的一个应用

    转载:http://www.cnblogs.com/vongang/archive/2012/05/04/2483419.html 记一个KMP算法的应用,经典的KMP算法详解还是看这里 问题:给一个 ...

  2. kmp算法 汇总

    来源:http://blog.csdn.net/qq_34494458/article/details/75253466 KMP算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,其 ...

  3. 真正理解KMP算法

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4403560.html 所谓KMP算法,就是判断一个模式串是否是一个字符串的子串,通常的算法当 ...

  4. KMP算法——从入门到懵逼到了解

    本博文參考http://blog.csdn.net/v_july_v/article/details/7041827 关于其它字符串匹配算法见http://blog.csdn.net/WINCOL/a ...

  5. (原创)白话KMP算法详解

    引子:BF暴力算法 KMP算法知名度相当高,燃鹅其理解难度以及代码实现对于初学数据结构和算法的同学并不友好,经过两天的总结,详细总结KMP算法如下: 初学串的模式匹配时,我们都会接触到,或者说应该能想 ...

  6. KMP算法的改进

    KMP算法的改进 KMP算法已经在极大程度上提高了子符串的匹配效率,但是仍然有改进的余地. 1. 引入的情景 下面我们就其中的一种情况进行分析: 主串T为"aaaabcde-" 子 ...

  7. KMP算法解析(转自图灵社区)

    KMP算法是一个很精妙的字符串算法,个人认为这个算法十分符合编程美学:十分简洁,而又极难理解.笔者算法学的很烂,所以接触到这个算法的时候也是一头雾水,去网上看各种帖子,发现写着各种KMP算法详解的转载 ...

  8. BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法

    标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...

  9. 串的模式之kmp算法实践题

    给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出.如果找不到,则输出“Not ...

随机推荐

  1. Java 之 反射

    1.反射 a.意义:允许运行中的Java程序对自身进行检查,或者说"自审",并能直接操作程序的内部属性 b.概括:运行时探究和使用编译时未知的类 c.反射的核心原理: ①JVM在加 ...

  2. leetcode--003 LRU cache

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABHAAAACmCAIAAAA9PO+sAAAgAElEQVR4nO3du3HbytvH8X8zqoB12A ...

  3. python中使用urllib2伪造HTTP报头的2个方法

    在采集网页信息的时候,经常需要伪造报头来实现采集脚本的有效执行 下面,我们将使用urllib2的header部分伪造报头来实现采集信息 方法1. ? 1 2 3 4 5 6 7 8 9 10 11 1 ...

  4. CentOS下架设VNC服务器

    CentOS下架设VNC服务器1.什么是VNC服务器?百度百科:VNC (Virtual Network Computer)是虚拟网络计算机的缩写.它 是一款优秀的远程控制工具软件,由著名的 AT&a ...

  5. iOS 设置UILable字体,及计算长度和位置

    UILabel *lastLable = [[UILabel alloc] init]; UIFont *font = [UIFont fontWithName:lastLable.font.font ...

  6. iOS 之 CALayer与UIView的区别

    最大区别:CALayer (图层)不会直接渲染到屏幕上. UIView是iOS系统中界面元素的基础,所有的界面元素都继承自它.它本身完全是由CoreAnimation来实现的. 真正的绘图部分,是由一 ...

  7. Chrome 控制台 如何调试javascript

    上面的文章已经大致介绍了一下console对象具体有哪些方面以及基本的应用,下面简单介绍一下如何利用好chrome控制台这个神器好好调试javascript代码(这个才是我们真正能用到实处的地方) 1 ...

  8. 数据库设计的误区—>CHAR与VARCHAR

    字符型字段是数据库表中最常见的字段,而字符型字段又分为定长和变长两种.一般来说,VARCHAR类型用于存储内容长度变化较大的数据,CHAR类型用于存储内容长度没有变化或变化不大的数据. 在数据的内部存 ...

  9. ORACLE获取字符串中数字部分

    ') from dual; select regexp_replace('23456中国3-00=.,45','[^0-9]') from dual;标签:regexp_replace regexp ...

  10. 如何在NodeJS项目中优雅的使用ES6

    如何在NodeJS项目中优雅的使用ES6 NodeJs最近的版本都开始支持ES6(ES2015)的新特性了,设置已经支持了async/await这样的更高级的特性.只是在使用的时候需要在node后面加 ...