这里写自定义目录标题
- 1. 什么是KMP算法
- 2. next数组的表示含义+怎么算
- 3. 匹配过程
- 例题——KMP字符串
1. 什么是KMP算法
KMP算法:给定abcabm字符串和abcabcabm字符串,求前面字符串在后面字符串出现的位置,我们从头开始依次遍历,当遍历到m!=c时候,本来应该再次从后面字符串的第二个位置从头开始遍历,但是kmp算法可以帮助我们直接从如下图开始再次遍历
为什么会出现如此操作?
原因是,我们先处理一遍要遍历的数组abcabm,然后再每个位置上存储一个角标,如果该位置出现匹配失败,那么我们就从该位置存储的角标处再重新遍历
那么此数组如何处理的?
2. next数组的表示含义+怎么算
next数组表示的是,字符串中,前缀和后缀相等的个数(前缀不算最前面的自己,后缀不算最后一个的自己)
如
aa 那么next[2] = 1 因为 a = a
aba 那么 next[3] = 1 因为 a = a
abab 那么 next[4] = 2 因为 ab = ab
aaa 那么 next[3] = 2 因为 jj = jj
算法如下
注意:
- j的大小 看前一个情况的变化而变化不一
- next[1] = 0,i从第二个开始求next
具体看代码,自己画图自己才能悟明白
for(int i = 2, j = 0; i <= m; i++)
{
while(j && p[i] != p[j+1]) j = next[j];
if(p[i] == p[j+1]) j++;
next[i] = j;
}
3. 匹配过程
for (int i = 1, j = 0; i <= m; i ++ )
{
while (j && s[i] != p[j + 1]) j = ne[j];
if (s[i] == p[j + 1]) j ++ ;
if (j == n)
{
printf("%d ", i - n);
j = ne[j];
}
}
- j 为什么从0开始?因为j要+1
if (s[i] == p[j + 1])
这个哪里来的?因为j回到起始位置,但第二个字符并没有去匹配,所以需要匹配一下