KMP算法模板(个人辛酸历程总结)

KMP模板(看了一个下午加一个晚上)

大家不要嫌我讲故事,我就亿点点自闭

KMP算法大家应该都知道是用来处理字符串快速查找的问题,通常会跟前缀后缀结合,时间复杂度很神奇O(m+n)!其中n、m分别为字符串长度。算法核心应该就是match数组(有些称next数组),以及匹配过程。对于原理,推荐去MOOC上看越姥姥数据结构的的KMP讲解,真的好懂,不过我感觉有些缺陷,个人感觉,对于做题不是很友好,(可能我太菜),一下展示我学到的姥姥的代码

//具体可以看姥姥的慕课,真的好懂
const int maxn=1e5+5;
int match[maxn];
void get_match(string s2){
	match[0]=-1;
	for(int j=1;j<s2.length();j++){
		int temp=match[j-1];
		while(temp>=0&&(s2[temp+1]!=s2[j])){
			temp=match[temp];
		}
		if(s2[temp+1]==s2[j]){
			match[j]=temp+1;
		}
		else match[j]=-1;
	}
}
int KMP(string s1,string s2){ //从s1里找s2
	if(s1.length()<s2.length()) return -1;
	get_match(s2);
	int s=0,p=0;
	while(s<s1.length()&&p<s2.length()){
		if(s1[s]==s2[p]) s++,p++;
		else if(p>0) p=match[p-1]+1;
		else s++;
	}
	if(p==s2.length()) return s-p;  //返回找到字串的下标
	else return -1; //没找到
}

学完后觉得不太难,我很高兴做完了姥姥的例题,觉得我学会了。直到最近要学AC自动机看了篇博客,说前提要学会KMP和tire树,于是重新看起KMP,使用了姥姥的模板,去洛谷,POJ上找了两题模板,发现了问题。而且几乎所有博客上的match数组都和姥姥的不太一样。可是我先入为主了,把姥姥的模板调试了一个下午都还是过不了,于是我去b站上看了灯神的KMP讲法,也是稀里糊涂了半天,下面贴下b站链接:这个吹爆
看了大概对match数组有了一定了解,但会发现和姥姥上的不太一样。。。
于是疯狂找博客,感觉在摸鱼
题目传送门:添加链接描述
感觉在这里插入图片描述
下午自己编的数据,以下都以这个为样例 S1=AAABAAABAA,S2=AAABAA

const int maxn=1e6+5;
int match[maxn];
char s1[maxn],s2[maxn];
int ans;
void get_match(char *s2){//一定要自己手动模拟,会发现很神奇
	int k=-1,j=0;//j表示当前位置
	match[0]=-1;
	int len=strlen(s2);
	while(j<len){
		if(k==-1||s2[k]==s2[j]){ //具体可以看我写的,真的神奇
			k++;
			j++;
			match[j]=k;
		}
		else{
			k=match[k];
		}
	}
}
int KMP(char* s1,char* s2){
	get_match(s2);
	int s=0,p=0;
	int len=strlen(s1),len2=strlen(s2);
	while(s<len){
		if(p==-1||s1[s]==s2[p]){
			s++;
			p++;
		}
		else p=match[p];
		if(p==len2){
			cout<<s-len2+1<<'\n'; //找到位置返回s-len2+1,若计数则ans++,p=match[p];
			p=match[p];
		}
	}
	return ans;
}

这段代码我个人感觉不是很好懂,我整整傻看了一个下午加一个晚上,心烦意乱,其实静下心来自己模拟一遍会发现很神奇,下面是我手写的一些过程,对自己以后也有帮助在这里插入图片描述
在这里插入图片描述

有了这个模板就可以做有些模板题了,仅仅是模板,看了HDU上有关KMP的题,觉着还是要对match数组有更深的了解,一下贴一下POJ的代码,就当以后自己的模板了,对于KMP的过程,下次补上。写这博客应该自己看的多,我也就瞎写了

//格式好丑,题目链接在上面
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<set>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<list>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int match[maxn];
char s1[maxn],s2[maxn];
int ans;
void get_match(char *s2){
 int k=-1,j=0;
 match[0]=-1;
 int len=strlen(s2);
 while(j<len){
  if(k==-1||s2[k]==s2[j]){
   k++;
   j++;
   match[j]=k;
  }
  else{
   k=match[k];
  }
 }
}
int KMP(char* s1,char* s2){
 get_match(s2);
 int s=0,p=0;
 int len=strlen(s1),len2=strlen(s2);
 while(s<len){
  if(p==-1||s1[s]==s2[p]){
   s++;
   p++;
  }
  else p=match[p];
  if(p==len2){
   cout<<s-len2+1<<'\n';
   p=match[p];
  }
 }
 return ans;
}
int main()
{
 scanf("%s%s",s1,s2);
 KMP(s1,s2);
 for(int i=1;i<=strlen(s2);i++){
  cout<<match[i]<<' ';
 }
 return 0;
 } 
 /*AAABAA
AAABAAABAAA*/

还是太菜了 傻看了那么久,还是好多题不会,别人应该看半小时就会了吧。以后还有好多东西要学

猜你喜欢

转载自blog.csdn.net/weixin_46173995/article/details/107550474