KMP算法&&扩展KMP算法(详解)

字符串匹配问题:有一个文本串S,和一个模式串P,现在让你查找P串在S串的位置。

1.朴素算法(暴力匹配)

  就是枚举的思想,比如S串现在匹配到第i个位置,P串匹配的第j个位置,这时候就会有匹配成功或者不成功

  如果匹配成功,就是P[j]==S[i] ,这时候则继续匹配下一个字符 i++ j++

  如果匹配失败   就是P[j]!=S[i] ,这个时候P就需要回到起始位置 ,S串回到 i-j+1这个位置 因为这次匹配P从0位走到了j位,所以S最开始是从i-j这个位置走的,但从i-j这个位置是最终是不能匹配成功的,所以

  我们需要从下一个位置开始匹配 ,也就是i-j+1

  代码实现:   

 1 int BF(char *S,char *P){
 2     int lens=strlen(S);
 3     int lenp=strlen(P);
 4     int i=0,j=0;
 5     while(i<lens&&j<lenp){
 6         if(S[i]==P[j]){
 7             i++;
 8             j++;
 9         }else{
10             i=i-j+1;
11             j=0;
12         }
13         if(j==lenp-1){
14             return i+1;//位序+1
15         }
16     }
17     return -1;
18 }

 

2.KMP算法

  KMP算法的经典之处起始就是next[]数组,所有的步骤都是围绕这个数组来进行的,上面的算法之所以叫做暴力匹配,就是因为在不匹配的情况下i j需要从头开始,导致时间复杂度达到O(m*n),m和n分别为两个串的长度,但其实在有些情况下我们是可以不需要重头开始匹配的。

  比如模式串P为abaabaca的情况下,假如我们匹配到第7个字符的情况下,j是可以不需要回到0的,因为前6个字符abaaba有一个很明显的特征 前三个和后三个的字符是一样的,假设模式P串匹配的位置是7,文本串S匹配的位置是i,那么i前面的6个字符也一定是abaaba,这时候虽然S和P匹配失败了,但P只需要从回到第4个位置重新进行匹配就可以了,

P a b a a b a c a              
S a b a a b a b a a b a c a    

  如上个表格,P走到第七个位置c,S走到底七个位置b,这时候两个字符是不匹配的,但是P是只需要回到第四个字符重新和S的第七个字符匹配就可以

                                     

 

  所以我们引入一个定义:最长公共前后缀,next[i]表示的就是前i个字符的最长公共前后缀的长度。

 我们需要处理处模式串P的next数组,假设next[i]=k的话,那就是P[0]P[1]..P[K-1]=P[i-k+1]P[i-k+2]...P[i-1]

 所以如果P[k]==P[i]的话 next[i+1]=k+1;否则就是next[i+1]=next[k]

 

posted on 2019-10-10 23:17  见字如面  阅读(133)  评论(0)    收藏  举报

导航