KMP算法模板与解析

全部数据结构、算法及应用课内模板请点击:https://blog.csdn.net/weixin_44077863/article/details/101691360

将KMP算法,就要先讲讲它是用来干什么的,为什么叫这个名字,暴力的算法又是怎样的

KMP是三人Knuth,Morris,Pratt,他们仨发明了这个算法,所以叫KMP。。。(不要惊讶。。)

然后它是用来解决字符串的模式匹配问题(大白话就是找子串)

举个例子说就是,给你一个主串 S ,模式串 T,问你S里含有多少个子串T,子串开头下标多少

比如 S=aaaaa T=aa,于是有4个子串,下标分别是0,1,2,3

再比如

有1个子串,下标5

然后说一说暴力的算法,也就是你没学过KMP保证就那样去写了

叫做BF算法,暴风(Brute Force)算法(就是暴力啦~),是普通的模式匹配算法

或者也可以叫做 NaiveStrMatching 朴素的模式匹配算法

暴力的方法事实上就是很单纯的二重循环,S下标0开始,然后每次T下标0开始去和S比较

时间复杂度O(nm)

然后人们意识到,T每次向后挪一位很没必要,然后从下标0开始一位一位地比较也完全没必要

比如还是上面那个ST

第一轮比较结果:

用人眼看的话,会觉得下一次比较有价值的比较是:

直接比较图中标记的p处

Naive的暴力算法接下来会比较:

并且挪到2号位的时候,T也会从0开始比较

这时候K、M、P三个人就开始研究人眼的匹配特性了

第一轮比较中,T匹配上的前缀串是 : ABAB

这一串有 真前缀串:A、AB、ABA

真后缀串:B、AB、BAB

他们发现,上述加粗的部分相同

于是规律性的东西出现了,我们再来看一下第一轮比较的图

对于T T01=T23,然后看后缀23,S23=T23=T01

于是将 T01挪至S23,并直接比较S4和T2即可

所以,KMP算法原理总结成一句话为:

比较失败时,看已匹配成功的前缀串A,取A的一个真后缀串Y,有一个A的真前缀串X与之相等

且此时lenX(=lenY)长度尽可能长,将X挪至Y的位置,直接比较X的下一个字符和失败位置的字符

不断循环以上操作,直到无法继续匹配

事实上,这个算法还远远没有说完

每次都现找后缀和与之对应的前缀,时间又是很复杂

于是要先预处理出来对应位置保存起来

比方说 ABAB 的 3号B 对应长度为 2(AB)

我们把这个称之为特征数N

对ABABA有

(教材是N,其实一般写作next会舒服些,但是包含万能头文件的话next会出现多义性报错)

于是这时我们再来看第一轮匹配

i=j=4时,匹配失败,于是移动后 j=N[ j-1 ],接着比较 S[ i ] 与 T[ j ] 即可

当然,如果 j=0(第一位)就已经不相等了就没有N[-1]了,就直接向后移动一位 i 就好

然后预处理特征数N的时候如果太过暴力又会很慢

用动态规划的思想去考虑,预处理这个东西的本质也是一个KMP

比方说4号位的A,N[ 3 ]=2,于是直接 主:T[ 4 ] 和 模式:T[ 2 ]比较

发现 T[4]==T[2],于是 N[4]=N[3]+1=3,接着判断第5位(当然上面这个串没有5,那就结束了)

假设 T[ 4 ] != T[ 2 ],那么就接着判断当前真前缀串的真前缀串的下一位,就是去找判断N[ N[ 3 ] - 1 ]即N[ 1 ]

然后不断重复这样的操作直到相等

当然,假设判断到 0 还不相等,那么 N[ 4 ]就=0

KMP算法模板如下:(复杂度O(n+m))

char s[maxn],t[maxm]; //主串s,模式串t 
int n,m,N[maxm],cnt; //主串长n,模式串长m,特征数N,成功匹配个数cnt
vector<int> pos; //成功匹配位置所有下标(第一个字符)
void get_next(){
	m=strlen(t);
	for(int i=1;i<m;i++){
		int j=N[i-1];
		while(j&&t[i]!=t[j]) j=N[j-1];
		if(t[i]==t[j]) N[i]=j+1;
		else N[i]=0;
	}
}
void KMP(){
	n=strlen(s);
	int i=0,j=0;
	for(;i<n;i++){
		while(s[i]!=t[j]&&j) j=N[j-1];               
		if(s[i]==t[j]) j++;
		if(j==m) cnt++,pos.push_back(i-j+1);
	}
}

KMP算法模板题:https://cn.vjudge.net/problem/HihoCoder-1015

可以交一发检验下自己写的KMP对不对

发布了49 篇原创文章 · 获赞 0 · 访问量 1718

猜你喜欢

转载自blog.csdn.net/weixin_44077863/article/details/102172106