KMP算法(原文出处http://blog.csdn.net/u011564456/article/details/20862555)

如果你看不懂KMP算法,那就看一看这篇文章(绝对原创,绝对通俗易懂)

 

KMP算法,俗称“看毛片”算法,是字符串匹配中的很强大的一个算法,不过,对于初学者来说,要弄懂它确实不易。整个寒假,因为家里没有网,为了理解这个算法,那可是花了九牛二虎之力!不过,现在我基本上对这个算法理解算是比较透彻了!特写此文与大家分享分享!

我个人总结了,KMP算法之所以难懂,很大一部分原因是很多实现的方法在一些细节的差异。怎么说呢,举我寒假学习的例子吧,我是看了一种方法后,似懂非懂,然后去看另外的方法,就全都乱了!体现在几个方面:next数组,有的叫做“失配函数”,其实是一个东西;next数组中,有的是以下标为0开始的,有的是以1开始的;KMP主算法中,当发生失配时,取的next数组的值也不一样!就这样,各说各的,乱的很!

所以,在阐述我的理解之前,我有必要说明一下,我是用next数组的,next数组是以下标0开始的!还有,我不会在一些基础的概念上浪费太多,所以你在看这篇文章时必须要懂得一些基本的概念,例如朴素字符串匹配”“前缀后缀等!还有就是,这篇文章的每一个字都是我辛辛苦苦码出来的,图也是我自己画的!如果要转载,请注明出处!好了,开始吧!

假设在我们的匹配过程中出现了这一种情况:

根据KMP算法,在该失配位会调用该位的next数组的值!在这里有必要来说一下next数组的作用!说的太繁琐怕你听不懂,让我用一句话来说明:

返回失配位之前的最长公共前后缀!

好,不管你懂不懂这句话,我下面的文字和图应该会让你懂这句话的意思以及作用的!

首先,我们取之前已经匹配的部分(即蓝色的那部分!)

我们在上面说到next数组的作用时,说到最长公共前后缀,体现到图中就是这个样子!

接下来,就是最重要的了!

没错,这个就是next数组的作用了:

返回当前的最长公共前后缀长度,假设为len。因为数组是由0开始的,所以next数组让第len位与主串匹配就是拿最长前缀之后的第1位与失配位重新匹配,避免匹配串从头开始!如下图所示!

(重新匹配刚才的失配位!)

 

如果都说成这样你都不明白,那么你真的得重新理解什么是KMP算法了!

 

接下来最重要的,也是KMP算法的核心所在,就是next数组的求解!不过,在这里我找到了一个全新的理解方法!如果你懂的上面我写的的,那么下面的内容你只需稍微思考一下就行了!

 

跟刚才一样,我用一句话来阐述一下next数组的求解方法,其实也就是两个字:

继承

a、当前面字符的前一个字符的对称程度为0的时候,只要将当前字符与子串第一个字符进行比较。这个很好理解啊,前面都是0,说明都不对称了,如果多加了一个字符,要对称的话最多是当前的和第一个对称。比如agcta这个里面t的是0,那么后面的a的对称程度只需要看它是不是等于第一个字符a了。

b、按照这个推理,我们就可以总结一个规律,不仅前面是0呀,如果前面一个字符的next值是1,那么我们就把当前字符与子串第二个字符进行比较,因为前面的是1,说明前面的字符已经和第一个相等了,如果这个又与第二个相等了,说明对称程度就是2了。有两个字符对称了。比如上面agctag,倒数第二个anext1,说明它和第一个a对称了,接着我们就把最后一个g与第二个g比较,又相等,自然对称成都就累加了,就是2了。 

c、按照上面的推理,如果一直相等,就一直累加,可以一直推啊,推到这里应该一点难度都没有吧,如果你觉得有难度说明我写的太失败了。

当然不可能会那么顺利让我们一直对称下去,如果遇到下一个不相等了,那么说明不能继承前面的对称性了,这种情况只能说明没有那么多对称了,但是不能说明一点对称性都没有,所以遇到这种情况就要重新来考虑,这个也是难点所在。

如果蓝色的部分相同,则当前next数组的值为上一个next的值加一,如果不相同,就是我们下面要说的!

如果不相同,用一句话来说,就是:

从前面来找子前后缀

1、如果要存在对称性,那么对称程度肯定比前面这个的对称程度小,所以要找个更小的对称,这个不用解释了吧,如果大那么就继承前面的对称性了。

2、要找更小的对称,必然在对称内部还存在子对称,而且这个必须紧接着在子对称之后。

 

如果看不懂,那么看一下图吧!

好了,我已经把该说的尽可能以最浅显的话和最直接的图展示出来了,如果还是不懂,那我真的没有办法了!

说了这么多,下面是代码实现

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #define N 100  
  5.   
  6. void cal_next( char * str, int * next, int len )  
  7. {  
  8.     int i, j;  
  9.   
  10.     next[0] = -1;  
  11.     for( i = 1; i < len; i++ )  
  12.     {  
  13.         j = next[ i - 1 ];  
  14.         while( str[ j + 1 ] != str[ i ] && ( j >= 0 ) )  
  15.         {  
  16.             j = next[ j ];  
  17.         }  
  18.         if( str[ i ] == str[ j + 1 ] )  
  19.         {  
  20.             next[ i ] = j + 1;  
  21.         }  
  22.         else  
  23.         {  
  24.             next[ i ] = -1;  
  25.         }  
  26.     }  
  27. }  
  28.   
  29. int KMP( char * str, int slen, char * ptr, int plen, int * next )  
  30. {  
  31.     int s_i = 0, p_i = 0;  
  32.   
  33.     while( s_i < slen && p_i < plen )  
  34.     {  
  35.         if( str[ s_i ] == ptr[ p_i ] )  
  36.         {  
  37.             s_i++;  
  38.             p_i++;  
  39.         }  
  40.         else  
  41.         {  
  42.             if( p_i == 0 )  
  43.             {  
  44.                 s_i++;  
  45.             }  
  46.             else  
  47.             {  
  48.                 p_i = next[ p_i - 1 ] + 1;  
  49.             }  
  50.         }  
  51.     }  
  52.     return ( p_i == plen ) ? ( s_i - plen ) : -1;  
  53. }  
  54.   
  55. int main()  
  56. {  
  57.     char str[ N ] = {0};  
  58.     char ptr[ N ] = {0};  
  59.     int slen, plen;  
  60.     int next[ N ];  
  61.   
  62.     while( scanf( "%s%s", str, ptr ) )  
  63.     {  
  64.         slen = strlen( str );  
  65.         plen = strlen( ptr );  
  66.         cal_next( ptr, next, plen );  
  67.         printf( "%d\n", KMP( str, slen, ptr, plen, next ) );  
  68.     }  
  69.     return 0;  
  70. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BF算法KMP算法在模式匹配中有一些区别。BF算法是一种简单直观的算法,它通过在主串和模式串之间进行逐个字符的比较来判断是否匹配。具体而言,BF算法在每次不匹配时,将主串的指针回溯到起始位置的下一个字符,并将模式串的指针重新指向模式串的起始位置。这种回溯的方式可能导致算法的效率较低。 而KMP算法通过预处理模式串,构建一个next数组来避免回溯。这个next数组存储了模式串中每个位置的最长前缀后缀的长度。在匹配过程中,当遇到不匹配的字符时,KMP算法可以根据next数组的值将模式串的指针移动到下一个匹配的位置,而无需回到主串的起始位置。这样可以有效减少不必要的比较次数,提高匹配效率。 因此,BF算法KMP算法的主要区别在于匹配不成功时的处理方式。BF算法通过回溯来重新匹配,而KMP算法通过利用next数组实现指针的跳跃,避免了不必要的回溯,提高了匹配效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [BF算法KMP算法](https://blog.csdn.net/weixin_48420408/article/details/121714883)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [bf算法kmp算法及改进的kmp](https://download.csdn.net/download/weixin_44019015/10836794)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [字符串的模式匹配详解--BF算法KMP算法](https://download.csdn.net/download/weixin_38658085/12808755)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值