KMP算法
当匹配字符串是ababcabaa时,被匹配的字符串是ababababcabaab时
q:ababababcabaab
p:ababcabaa
先模拟一下简单匹配
ababababcabaab
ababcabaa
11110
ababababcabaab
ababcabaa
0
ababababcabaab
ababcabaa
11110
.......
匹配过程:
1. 当从被匹配字符串的第一个字符开始与匹配,当被匹配字符串和匹配字符串中的字符不同的时候为0 匹配失败
2. 然后从被匹配字符串的后一个字符开始再与匹配字符串一个个匹配,速度很慢
3. KMP算法可以加速匹配,通过移动匹配字符串
KMP算法先处理匹配字符串 计算next数组
1.首先初始化next数组都为-1
2.从匹配字符串下标为1的字符i开始,取出上个字符i-1的next值j,
3.若p[j+1] != p[i]且j!=-1,往前寻找 j=next[j]
4.若p[j+1] == p[i],next[i] = j+1
看一下例子 p=abcaba,默认为-1,-1,-1,-1,-1,-1
i = 1 j = next[0] = -1 不满足操作3 p[j+1] != p[i] 不满足操作4 next值不变
i = 2 j = next[1] = -1 不满足操作3 p[j+1] != p[i] 不满足操作4 next值不变
i = 3 j = next[2] = -1 不满足操作3 p[j+1] == p[i] 满足操作4 next[i]=j+1 next[3]=0
i = 4 j = next[3] = 0 p[j+1] == p[i] 不满足操作3 满足操作4 next[i]=j+1 next[4]=1
i = 5 j = next[4] = 1 p[j+1] != p[i] 满足操作3 j = next[j] = -1 不满足操作3 p[j+1] == p[i] 满足操作4 next[5]=0
最后next数组为[-1,-1,-1,0,1,0]
KMP匹配操作:
1. j从-1开始,遍历被匹配字符串q
2. 若 j != -1 且 p[j+1] != q[i] 则 j= next[j] 调整p的下标继续匹配
3. 若匹配则匹配字符个数++
ababcabaa的next数组为[-1,-1,0,1,-1,0,1,2,0]
根据KMP再模拟一下匹配
q ababababcabaab
p ababcabaa
11110
当 j = 3,i = 4 时 p[j+1] != q[i],满足操作2 j= next[j] = 1,于是匹配变成
q ababababcabaab
p ababcabaa
111
继续判断当 j = 1,i = 4时,发现满足操作3,匹配字符++,直到
q ababababcabaab
p ababcabaa
11110
重复之前的操作,找到匹配,发现速度很快
q ababababcabaab
p ababcabaa
111111111
模版代码
class Solution {
public:
bool kmp(const string& q, const string& p) {
int m = q.size();
int n = p.size();
vector<int> next(n,-1);
for(int i = 1;i < n; i++){
int j = next[i-1];
while(j != -1 && p[j+1] != p[i]){
j = next[j];
}
if(p[j+1] == p[i]){
next[i] = j+1;
}
}
int j = -1;
for(int i = 1;i < m-1; i++){
while(j != -1 && p[j+1] != q[i]){
j = next[j];
}
if(p[j+1] == q[i]){
j++;
if(j == n-1){
return true;
}
}
}
return false;
}
};
今天也是爱zz的一天哦!