【原创】朴素的模式匹配和改进的模式匹配(KMP)算法说明(草稿)

朴素的模式匹配和改进的模式匹配(KMP)算法说明
   LEWISLAU
前言:最近复习数据结构,以前老师讲的时候居然忽略了串。汗,我们学校的确牛B。某仁兄告诉我,KMP基本是数据结构里面难度比较大的算法了,所以掌握了它,至少从心理上给我了很大的鼓舞,但是这个算法是我询问老师才掌握的,呵呵。言规正传,开始说KMP算法。
在说改进的模式匹配(KMP)算法之前我们先说朴素的模式匹配:
其实很简单,就是两个字符串逐位比较。在模式匹配中:我们假定字符串P在字符串T中查找是否有匹配的。此时,称P为模式(Pattern)字符串,称T为目标(Target)字符串。
OK,我一般比较喜欢以实例说明问题。
T:        a  b  d  a  b  d  a  b  c
P:        a  b  d  a  b  c

朴素的模式匹配算法

朴素的模式匹配算法就是用P和T依次比较,即为:
第一趟比较:   T:        a  b  d  a  b  d  a  b  c
   P:        a  b  d  a  b  c
               发现第6个元素(下标为5)d和c不相等,第一趟结束,此时比较了6次(6个元素)。
第二趟比较:   T:        a  b  d  a  b  d  a  b  c
   P:           a  b  d  a  b  c
                   第一个元素就不相等,第二趟结束,此时比较了1次(1个元素)。
第三趟比较:   T:        a  b  d  a  b  d  a  b  c
   P:              a  b  d  a  b  c
         第一个元素就不相等,第三趟结束,此时比较了1次(1个元素)。
第四趟比较:   T:        a  b  d  a  b  d  a  b  c
   P:                 a  b  d  a  b  c
         第一个元素相等,第二个元素也相等,第三、四、五、六都相等,匹配成功,第四趟结束,此时比较了6次(6个元素)。
匹配成功,共比较14次。但是这个是我们理想状态下的匹配方案,实际中字符串的长度远远不止这些。这种算法是一种带回逆的算法,成为朴素的模式匹配算法。
假定:目标T长度为n,模式P长度为m,那么它的最坏情况下,会比较次数可达到:
 (n - m + 1)*m  次;在众多场合下m远远小于n,它的时间复杂度为O(n * m)。


改进的模式匹配(KMP)算法

KMP算法就是消除了朴素匹配的回逆,利用一个失效函数(failure function)替代直接的回逆。思路如下:
第一趟比较:   T:        a  b  d  a  b  d  a  b  c
   P:        a  b  d  a  b  c
               发现第6个元素(下标为5)d和c不相等。此时,进入一个P串的处理:
此时取出P串,      a  b  d  a  b  c    因为是c不和d不匹配,去掉此项,获得
a  b  d  a  b  
此时判断  a  b  d  a  是否与 b  d  a  b  相等? 不等,进入下一轮判断
此时判断  a  b  d     是否与 d  a  b     相等? 不等,进入下一轮判断
此时判断  a  b        是否与 a  b        相等? 相等,结束第一趟总体判断。
(先不要急,接下来我就会说为什么这样匹配和这样匹配的用途!)
以上就是KMP的流程,为什么要这样做?在一些串中,目标串会远远长于模式串,如果每次都江模式串和目标串一一比较。此时时间复杂度当增加,而且在模式串中会出现很多的无效匹配,相当于无用功。但是假如先在模式串中进行比较,因为模式串会远远短于目标串,所以会相当减少时间复杂度。
以上是KMP的简单介绍,有机会会整理出详细算法及其优势!
其他不想多说,只想说明“算法是程序的灵魂!”这一古老而经典的话!!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
KMP改进算法是一种用于串的模式匹配的高效算法。以下是对KMP改进算法代码的注解。 在KMP改进算法中,通过预处理模式串,构建一个部分匹配表(partial match table),这个表记录了在模式串中每个前缀的最长真前缀后缀长度。这个部分匹配表是在O(n)的时间复杂度内构建的,其中n是模式串的长度。 代码注解如下: 1. 构建部分匹配表 a. 初始化一个与模式串等长的部分匹配表next。 b. 设置两个指针i和j,初始值分别为0和-1。 c. 循环迭代i从0到n-1,其中n是模式串的长度。 i. 在循环内,判断j是否大于等于0且模式串中的第i个字符与模式串中的第j个字符不匹配。 如果条件成立,将j设置为next[j],以回溯到前一个最长真前缀后缀长度。 ii. 在循环内,判断模式串中的第i个字符与模式串中的第j个字符是否匹配。 如果条件成立,将i和j的值分别加1。 设置next[i]为j,表示在字符串的第i个字符之前的最长真前缀后缀长度。 2. 匹配过程 a. 初始化两个指针i和j,分别指向文本串和模式串的开头。 b. 循环迭代i从0到文本串的长度减去模式串的长度。 i. 在循环内,判断j是否大于等于0且文本串中的第i个字符与模式串中的第j个字符不匹配。 如果条件成立,将j设置为next[j],以回溯到前一个最长真前缀后缀长度。 ii. 在循环内,判断模式串中的第j+1个字符与文本串中的第i+j+1个字符是否匹配。 如果条件成立,将j的值加1。 如果j等于模式串的长度减1,表示找到了匹配的位置,输出结果。 c. 如果循环结束后仍未找到匹配的位置,表示没有匹配的子串。 KMP改进算法通过预处理模式串,避免在匹配过程中重复比较已经比较过的字符,从而提高了匹配的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值