复习—KMP算法

对于KMP算法的学习,在寒假时我还是搞不太明白,但几个月之后,对于它的理解又更近了一步。

首先是对于子串的自我匹配,求一个fail数组,fail[i]对于字符串SS的前ii个字符构成的子串,既是它的后缀又是它的前缀的字符串中(包括他),最长的长度记作fail[i]

举个例子,abcdabc中fail[7]的值就是3。当我们失配的时候,就直接跳到fail[i]所指的值上,这样效率就提升很大。

同理,子串和模式串匹配也是这个套路。对于KMP算法的讲解,建议去bilibili上有一个印度人的视频讲的还比较清楚。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+7;
int fail[maxn],show[maxn];
char s1[maxn],s2[maxn];
int ans;
int len1,len2;
int j;
void getfail(){
    fail[1]=0;
    for(int i=2;i<=len2;i++){
        while(j!=0&&s2[i]!=s2[j+1]) j=fail[j];
        if(s2[i]==s2[j+1]) j++;
        fail[i]=j;
    }
} 
void kmp(){
    j=0;
    for(int i=1;i<=len1;i++){
        while(j!=0&&s1[i]!=s2[j+1]) j=fail[j];
        if(s1[i]==s2[j+1]) j++;//母串不动,子串自己动
        if(j==len2){
            ans++;
            show[ans]=i-len2+1;//求子串出现的位置
        } 
    }
}
int main(){
    scanf("%s%s",s1+1,s2+1);
    len1=strlen(s1+1);
    len2=strlen(s2+1);    
    getfail();
    kmp();
    for(int i=1;i<=ans;i++){
        printf("%d\n",show[i]);
    }
    for(int i=1;i<=len2;i++){
        printf("%d ",fail[i]);
    }
    return 0;
}

 

posted @ 2019-06-15 10:31  JBLee  阅读(220)  评论(0编辑  收藏  举报