字符串匹配 KMP算法 模板

KMP:Knuth(D.E.Knuth)、Morris(J.H.Morris)和Pratt(V.R.Pratt)三人设计的线性时间字符串匹配算法。KMP算法是字符串匹配的经典算法。KMP算法是通过分析子串,预先计算每个位置发生不匹配的时候,直接移动到下一个”恰当“的位置。其中的关键是计算jump数组。(相关证明可以看算法导论二版32.4)

时间复杂度为O(n);

/*kmp相关ojhttp://www.cnblogs.com/wuyiqi/archive/2012/01/06/2315188.html*/
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
const int T=1000009;
const int W=10009;
/*在jump数组中,发现str[k+1]!=str[i]时,当前的最长proper后缀不能完全匹配字符串的前缀 ,
当前的后缀需要缩短后再尝试。
要求缩短后的后缀也要是字符串的一个前缀时,就意味着在str[i-k+x..i]中(x<=k,其实就是str[i-k..i]的proper后缀)
寻找一个x使得str[i-k..i]的后缀str[i-k+x..i]为整个字符串的一个前缀。
由于str[i-k..i]与str[1..k]完全匹配,问题就转化成了求str[1...k]的最长proper后缀为字符串前缀,也就是jump[k]。*/
void getp(const char *str,int len,int *&jump){//string from the index of 1
    jump=new int[len+1];//is the proper suffix str' length for longest prefix
	jump[1]=0;//
	int k=0;
	for(int i=2;i<=len;i++){
		while(k>0&&str[k+1]!=str[i])
				k=jump[k];//if this suffix it not the prefix,decrease suffix size
		if(str[k+1]==str[i])
			k=k+1;
		jump[i]=k;    
	}
}
int kmp(const char *s,const char *t){//string from the index of 1
    if(s==NULL||t==NULL)
        return 0;
    int len_s=strlen(s+1);
    int len_t=strlen(t+1);
	int *jump,i,count=0;
	int j=0;//number of charachers matched
	    getp(s,len_s,jump);
	for(i=1;i<=len_t;i++){
		while(j>0&&s[1+j]!=t[i])
			j=jump[j];//next character does not match, decrease match number to jump[j]
		if(s[1+j]==t[i])
			j++;//nes character matcheds,matched number ++
		if(j==len_s){//is all of  pattern matched?
			count++;
			j=jump[j];//look for the next match
		}
	}
    return count;
}
int main(){
    int n;
    char w[W],t[T];
    scanf("%d",&n);
    while(n--){
        scanf("%s%s",w+1,t+1);
        int count=kmp(w,t);
        printf("%d\n",count);
    }
    return 0;
}

例题:

KMP 的直接使用:http://poj.org/problem?id=3461

参考:

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