比如说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;
}