浅学KMP算法

本cg在学习了kmp算法之后感叹道这个算法的奇妙之处,网上有很多关于其的原理,这里我就不再赘述了,但是直接了当的kmp代码确实是很少,所以为了帮助各位提高效率和自己巩固写了这篇文章。

首先还是说一下kmp算法是干什么的吧,kmp算法是用来找字串的,算是数据结构中的难点了,理解起来也比较费劲,有人就说了,学这干什么,不如直接substr。nonono,stl大法虽好,可不能贪杯啊,kmp算法即是高效找字串的方法,一般的方法发现不匹配之后就直接回到起始,大大降低了效率,但此算法不同,可以记住最近的匹配点,提高效率,好了,废话不多说,直接上代码

 

#include
#include
using namespace std;
int nexts[2000000];
void getnext(string s)
{
	nexts[0]=0;
	int i=1,j=0;
	while(i=s2.length())
		return true;
	else
		return false;

}

int main()
{
	int n;cin>>n;
	string s1,s2;cin>>s1>>s2;
	s1+=s1;
	if(kmp(s1,s2))
		cout<<"wow"<

如果是为了拿板子的话,可以润了,别忘了点个赞。

接下来,分析一下代码,kmp最关键的即使next数组和nextval数组的构建,浅显的讲一下next数组和nextval的构建,nextval可以理解为next的升级办,提高了原有的效率。

首先next数组,一般我们从下标为0开始,并将其定义为0.然后从字符串的下标为0,next数组的下标为1,开始,然后next数组的值即为字符串此下标前的字符相同前后缀的长度加1,比如aabaab,当前字符下标为5的时候,前面有五个字符,前后缀的最大相同长度为2,则此next数组的值为2+1=3。以此类推,因为第一个字符前面没有东西,所以将next【0】定义为0.

来看getnext

void getnext(string s)
{
	nexts[0]=0;
	int i=1,j=0;
	while(i

记录i为next数组开始下标,j为next数组的值。如果j为0则意味着前方没有相匹配的,即是最坏的情况,若不为0,则直接在原有的基础上加一,至于为什么,可以看其他的深入讲解。如果两个都不满足的话,怎么办?那么直接就去看门牌(谐音kmp)即j直接变成以j为下标的next数组的值,最后不断循环,next数组就求出来了;

接下来看nextval

void getnextval(string s)
{
	int i=1;
	nextval[0]=0;
	while(i

nextval的原理即是如果在i位置的字符s[i]如果等于以next【i】的值为下标处的字符串中的字符的话,那么nextval【i】的值就是nextval【next【i】】的值,否则是自身的next【i】的值。

最后看总体kmp

bool kmp(string s1,string s2)
{
	int i=0,j=0;
	getnext(s2);getnextval(s2);
	while(i=s2.length())
		return true;
	else
		return false;

}

i和j分别源串和字串的下标,如果两个字符相匹配,则继续往下匹配,否则将子串的下标回溯到nextval的值,这就是我们求nextval的意义,用来回溯,避免重复计算。最后如果字串顺利循环完,那么说明匹配成功了,要么那就是失败了。自此,kmp算法就结束了,是不是还不算复杂啊,当然这只是将结论以代码的形式呈现出来,想要深刻了解,可以去看看视频。最后希望大家多给我这个ruog点赞-——来自大一cg的乞讨

你可能感兴趣的:(字符串算法,算法,c++,数据结构)