KMP算法

前置概念:

  • 字符串匹配:查找一个字符串在另一个字符串中有多少个,并得到它们的位置
  • 模式串:用于匹配的字符串(例如在abcabc中查找abc,则abc是模式串)
  • 匹配主串:用于被匹配的字符串(例如在abcabc中查找abc,则abcabc是匹配主串)
  • KMP算法:单模式串的字符串匹配算法
  • AC自动机*:多模式串的字符串匹配算法(基于trie树和kmp算法的思想)

算法思想:

  • 充分利用模式串内部的信息以减少时间复杂度,也就是通过预处理模式串减少字符串匹配时的匹配次数

算法过程:

  • 进行模式串的预处理,也就是计算next数组
  • 进行字符串匹配,也就是进行KMP算法的主过程

模板地址:https://www.luogu.org/problemnew/show/P3375


 个人思路:

  • KMP()与get_next()方法一个是对匹配串进行匹配,另一个是计算模式串的next数组.
  • 两个方法都有两个局部变量index和nowvalue,分别指示当前匹配位置和当前next值。所不同的是,KMP()方法中由于不需要对next数组进行初始化,nowvalue只需初始化为0,而get_next()方法中由于需要增加不可匹配的特殊判断值,所以next[0]和nowvalue都要初始化为-1
  • KMP()方法中nowvalue==len2指匹配长度达到要求。这时候输出一个答案为当前位置即可.
  • KMP()方法中如果当前字符匹配成功则直接将index和nowvalue后移一位即可,而在模式字符串自我匹配中只需要对下一位的next数组进行初始化,也就是next[++index]=++nowvalue.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int SIZE=1000001;
int n,k,len1,len2;
int next[SIZE];
char s1[SIZE],s2[SIZE];
void get_next(){
	int index=0,nowvalue;//位置和当前位的next值 
	next[0]=nowvalue=-1;//设置第一位为无法向前跳转 
	while(index<len2){
		if(nowvalue==-1||s2[index]==s2[nowvalue])next[++index]=++nowvalue;
		//如果当前next值为-1或匹配成功,则下一位的next值增加 
		else nowvalue=next[nowvalue];//如果匹配失败,则next值 向前跳转 
	}
}
void KMP(){
	int index=0,nowvalue=0;
	while(index<len1){
		if(nowvalue==-1||s1[index]==s2[nowvalue])
			index++,nowvalue++;
		else nowvalue=next[nowvalue];
		if(nowvalue==len2)printf("%d
",index-len2+1); 
	}
}
int main(){
	scanf("%s",s1);
	scanf("%s",s2);
	len1=strlen(s1),len2=strlen(s2);
	get_next();
	KMP();
	for(int i=1;i<=len2;i++)
		printf("%d ",next[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680651.html