KMP讲解推荐视频(来源于https://www.bilibili.com):
参考视频1
参考视频2
定义:
真前缀:对于当前位置i,从0~k(0<=k 真后缀:对于当前位置i,从k~i(1<=k<=i)构成的子串;例如:abcd的真后缀有bcd,cd,d
最长公共真前、后缀:真前缀和真后缀相同,而且长度最长;例如:aaaa的最长公共真前、后缀为aaa,长度为3;abab的最长公共真前、后缀为ab,长度为2
next数组的含义:next[i]:存放i之前子串(0~i-1共i个字符构成)的最长公共真前、后缀的长度。
手算Next数组:
对于模式串ababaabab,手算代码中getNext1中的Next数组(next1)和getNext2中的Next数组(next2)
tmp[i]: 对于下标i,存放0~ i的最长公共真前、后缀长度
next1[i]: next1[0]=-1,对于下标i,存放0~(i-1)的最长公共真前、后缀长度;若下标从1开始,则加1即可
next2[i]: next2[0]=-1,对于下标i,若next1[i]!=tmp[i]-1则为next1[i],否则为next2[ next1[i] ];若下标从1开始,则加1即可
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
字符 | a | b | a | b | a | a | b | a | b |
tmp[i] | 0 | 0 | 1 | 2 | 3 | 1 | 2 | 3 | 4 |
tmp[i]-1 | -1 | -1 | 0 | 1 | 2 | 0 | 1 | 2 | 3 |
next1[i] | -1 | 0 | 0 | 1 | 2 | 3 | 1 | 2 | 3 |
next2[i] | -1 | 0 | -1 | 0 | -1 | 3 | 0 | -1 | 0 |
题目链接
题意:查找模式串t在主串s中出现的次数。
参考代码:
//HDU 1686 查找模式串t在主串s中出现的次数,模式匹配,KMP算法
#include
#include
#include
using namespace std;
string s, t; //s主串,t模式串
vector Next; //外部数组、变量不取名为next以免编译错,类似于max,min,count不作为外部变量名
int n, m; //s主串长度n,t模式串长度m
void getNext1() // O(m),计算Next数组的方法
{
int i=0, j=-1;
Next[0]=-1;
while(i>t>>s; //输入模式串和主串
n=s.size(); //主串长度
m=t.size(); //模式串长度
//简单起见(i++后next[i]=j不用判断i下标越界),最后一个字符后的位置也计算一下next值,
Next.resize(t.size()+1);
getNext1();
//Next.clear();
//getNext2();
int pos=-1;
cout << KMP(pos) <