kmp算法的理解

时间:2020-02-10 13:59:18   收藏:0   阅读:50

我发现想出kmp算法的人tql,我理解都要理解半天(太抽象了QAQ)。

kmp代码的自己理解:

#include <string>
#include <iostream>
#include <vector>
using namespace std;
const int N = 10000;

int ne[N];

void getne(string p){
    int len=0;
    //len表示最长公共前后缀的长度
    ne[0]=0;
    //第一个字母的ne初始化为0由于以后会向右移动一位那么当前所表示的位置其实是后一位匹配错的时候应该回溯的位置
    for(int i=1;i<p.size();i++){
        while(len>0&&p[len]!=p[i])len=ne[len-1];
        //由于这里的len每次指的是前一个位置的最大前缀的后面一位的位置,所以就要匹配当前位置和i的字母是否匹配,如果不匹配那么就应该找前缀的最长公共前缀(相当于是递归搜索)
        //如果len等于了i那么就把len++
        if(p[len]==p[i])len++;
        ne[i]=len;
    }
    //这里是把ne数组向后移一位目的是为了以后处理匹配的时候方便
    for(int i=p.size();i>0;i--){
        ne[i]=ne[i-1];
    }
    ne[0]=-1;
}


vector<int> kmp(string base,string s){
    getne(s);
    vector<int> res;
    int i=0,j=0;
    while(i<base.size()){
        if(base[i]==s[j]){
            if(j==s.size()-1){
                //如果匹配到了那么就把开头的位置添加进来
                res.push_back(i-j);
                j=ne[j];
            }
            else {
                //如果当前位置一样就匹配下一位
                i++;
                j++;
            }
        }
        else {
            if(ne[j]==-1){
                //如果第一位都不一样,那么就i和j都向后移(意思是整个字符串向后移)
                i++;
                j++;
            }
            else {
                //如果中间某个位置不匹配,那么就移到它的ne的位置继续匹配,由于前后缀相同所以ne前的位置上的字符一定是符合的
                j=ne[j];
            }
        }
    }
    
    return res;
}
int main(){
    int n,m;
    cin>>n;
    string s1;
    cin>>s1;
    cin>>m;
    string s2;
    cin>>s2;
    auto res=kmp(s2,s1);
    for(int i=0;i<res.size();i++){
        cout<<res[i]<<" ";
    }
}

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!