字符串匹配 -kmp算法

解决对象:给定一个主串(以 S 代替)和模式串(以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题。

  • 1 暴力求解法:

暴力匹配的时间复杂度为 O(nm),其中 n 为 S 的长度,m 为 P 的长度。很明显,这样的时间复杂度很难满足我们的需求。

代码:

int naiveStringSearch(string S, string P){
    int i = 0,j = 0;
    int lens = S.length(),lenp = P.length();
    while(i<lens&&j<lenp){
         if(S[i]==P[j]){
               i++;
               j++;
         }else{
              i = i-j+1;
              j = 0;
         }
    }
    if(j==lenp){
        return i-j;
    }
    return -1;
}
  • 2 kmp求解:

假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置
如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]。此举意味着失配时,模式串P相对于文本串S向右移动了j – next [j] 位。”
我们发现如果某个字符匹配成功,模式串首字符的位置保持不动,仅仅是i++、j++;如果匹配失配,i 不变(即 i 不回溯),模式串会跳过匹配过的next [j]个字符。整个算法最坏的情况是,当模式串首字符位于i – j的位置时才匹配成功,算法结束。
所以,如果文本串的长度为n,模式串的长度为m,那么匹配过程的时间复杂度为O(n),算上计算next的O(m)时间,KMP的整体时间复杂度为O(m + n)。

代码:

void next(string p,int a[]){    //模式串next化
    int lenp = p.length();
    a[0] = -1;
    int i = 0,j = -1;
    while(i<lenp){
        if(j==-1||p[i]==p[j]){
           i++;
           j++;
           a[i] = j;
        }else{
           j = a[j];
        }
    }
}
int kmp(string s,string p,int b[]){
    next(p,b);         //模式串next化
    int i = 0,j = 0;
    int lens = s.length(),lenp = p.length();
    while(i<lens&&j<lenp){
         if(j==-1||s[i]==p[j]){
               i++;
               j++;
         }else{
               j = b[j];    //匹配不成功,跳转
         }
    }
    if(j==lenp){           //匹配成功
        return i-j;
    }
    return -1;
}

完整代码:

​
/**
   @字符串匹配-kmp算法
*/
#include<bits/stdc++.h>
#define MAX 100
using namespace std;
/*普通算法
int naiveStringSearch(string S, string P){
    int i = 0,j = 0;
    int lens = S.length(),lenp = P.length();
    while(i<lens&&j<lenp){
         if(S[i]==P[j]){
               i++;
               j++;
         }else{
              i = i-j+1;
              j = 0;
         }
    }
    if(j==lenp){
        return i-j;
    }
    return -1;
}*/
void next(string p,int a[]){    //模式串next化
    int lenp = p.length();
    a[0] = -1;
    int i = 0,j = -1;
    while(i<lenp){
        if(j==-1||p[i]==p[j]){
           i++;
           j++;
           a[i] = j;
        }else{
           j = a[j];
        }
    }
}
int kmp(string s,string p,int b[]){
    next(p,b);         //模式串next化
    int i = 0,j = 0;
    int lens = s.length(),lenp = p.length();
    while(i<lens&&j<lenp){
         if(j==-1||s[i]==p[j]){
               i++;
               j++;
         }else{
               j = b[j];    //匹配不成功,跳转
         }
    }
    if(j==lenp){           //匹配成功
        return i-j;
    }
    return -1;
}
int main(){
   string s,p;
   cin>>s>>p;
   int a[20] = {0};
   if(kmp(s,p,a)!=-1){
       cout<<"匹配位置下标为:"<<kmp(s,p,a)<<endl;
   }else{
       cout<<"匹配失败"<<endl;
   }
}
/*
bbcabcdababcdabcdabde
abcdabd
*/


​
  • 结果:

 《字符串匹配 -kmp算法》

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/lfb637/article/details/81104149
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞