Bootstrap

KMP算法之C++代码的实现(详解版!)

比如说abcabcf next数组为{0,0,0,1,2,3,0}

1.初始化
2.前后缀不相等的情况
3.前后缀相等的情况
4.更新next数组的值

#include<iostream>
#include <vector>
using namespace std;


vector<int> Getnext(char* s) //s为更短的字符串
{
	int n = strlen(s);  //求s的长度
	vector<int> next;    //next数组
	int j = 0, i;  //j表示前缀的末尾值,也代表公共字符串的值。比如说abcabc 当j指向c时,此时的j=2,

	next.push_back(0); //对于next数组中的第一个数,一定为0.
	for (int i = 1;i != n;++i)  //从i=1开始遍历,比较s[i]和s[j]
	{ 
		//分为相等和不相等两种情况
		if (s[i] == s[j])
		/*
		如果相等的话,j做加1操作,并把此时的j放入next数组中
		*/
		{
			++j;
			next.push_back(j);
		}

		//如果不相等的话,需要回溯,至于为什么要回溯,请去看kmp算法的原理emmm。
		//j代表的是前缀的末尾值
		else 
		{
				//巧妙之处,下面这条语句很经典,需要通过草稿纸例子才能理解(为什么是while呢)
				while(j>0 && s[i]!=s[j])
				{
					j = next[j - 1];
				}   
				if (s[i] == s[j])  //通过上面这条while语句的回溯,如果两个新的值是相等的,直接对j进行+1操作。
				{
					++j;
				}
				next.push_back(j);  //更新行的next数组值
		}

	}
	return next;  //遍历结束,返回next数组
}

//p为更长的字符串,s为更短的字符串
bool kmp(char* p, char* s)
{
	vector<int> next= Getnext(s);
	int j = 0;
	for (int i = 0;i != strlen(p);++i)
	{
		while (j > 0 && p[i] != s[j]) 
		{
			j = next[j - 1];
		}
		if (p[i] == s[j]) 
		{
			++j;
		}
		if (j == strlen(s))  //等j的长度遍历完了,返回true。
		{
			return true;
		}
	}
	return false; //否则,返回false
}


int main()
{
	char m[] = "abcabcd";
	char n[] = "abcabc";
	cout << kmp(m,n);
	return 0;
}
;