KMP复习小结

kmp能够实现单模板串的快速匹配。

备忘:cstring 头文件里的char* strstr 函数也是比较一个字符串是否为另一个字符串的子串,与KMP功能相同,速度究竟谁快?

经过测试,aaaaaa…….aaaab(len =1000) 去匹配 aaaaaaa…..aaab(len=1000000)

strstr 函数用了将近一秒钟,而kmp算法只花了不到0.1秒的时间。除了这种极端的情况外,其他一般情况strstr与kmp表现相当。

比赛中有时候可以用strstr水过。

kmp基本概念和原理略去,直接上next数组。

  0 1 2 3 4 5
str a b c a b
next -1 0 0 0 1 2

当匹配到s[i]失配时(也就是s[i]与文本串不匹配),i 跳到next[i-1]+1。

next(jump)数组构建过程正确性的归纳证明:

KMP算法中jump数组的构建可以通过归纳法来解决,首先确定jump[1]=0;假设jump[j]=k,

也就是P[0, k] == P[j-k, k],如果P[j+1] == P[k+1],那么得出[0,k+1] = P[j-k, j+1],从而

更加定义得出jump[j+1] = k+1;

如果P[j+1] != P[k+1],那就接着比较P[j+1] ?= P[k1+1],其中(jump[k] = k1),根据

(jump[k]=k1)的定义,P[0,k1] == P[k-k1, k],根据(jump[j]=k)的定义,P[0, k] ==

P[j-k, k],根据这两个等式,推出P[0, k1] == P[j-k1, j],如果此时P[j+1] == P[k1+1],则

得出:jump[j+1] = K1 +1 = jump[k] +1。

如果P[j+1] != P[K1+1],继续递归比较P[j+1] 和P[jump[jump[k]]+1] …. P[1];

如果依次比较都不相等,那么jump[j+1] = 0;写成代码如下,可以看出其实就是模式串自我

匹配的过程。

//生成jump(又叫next) 数组的函数,其中str下标从1开始,str[0] 为空,则jump[0] = -1 ,

void PrintJump(char *str){   //其中str下标从1开始,str[0] 为空,则jump[0] = -1 
    jump[0] = -1;
    jump[1] = 0;
    int len = strlen(str+1);
    int j=1,k;
    while(j<len){           //计算jump[j+1]
        k = jump[j];        //已知jump[j]==k
        while(k!=-1&&str[k+1]!=str[j+1]) k = jump[k];
        jump[j+1] = k+1;
        j++;
    }
}

//如果在s1中找到s2,返回真。同样地s2下标从1开始,s1下标从0开始。

bool Find(char *s1,char *s2){
    int i=0,j=1;
    while(1){
        if(j&&s2[j]=='') return true;
        else if(s1[i]=='') return false;
        if(j==0||s1[i]==s2[j]) {i++;j++;}
        else j = jump[j-1]+1;
    }
}
int main() {
    scanf("%s%s",str1,str2+1);
    PrintJump(str2);
    if(Find(str1,str2)) puts("yes");
    else puts("no");
}
原文地址:https://www.cnblogs.com/lastone/p/5308044.html