AcWing 831. KMP字符串(含个人理解与注释)
原题链接
简单
作者:
现代修士o_O
,
2021-04-22 20:20:52
,
所有人可见
,
阅读 307
//kmp算法,能快速地求出模板串 P 在模式串 S 中所有出现的位置的起始下标,终点下标。
#include <iostream>
using namespace std;
const int N = 100010, M = 1000010;
int n, m;
char p[N], s[M];
int ne[N];
int main()
{
cin >> n >> p + 1 >> m >> s + 1;//个人理解,从1开始的好处,j下标是多少,也就以为着成功匹配了多长。形象理解
//求ne数组, ne[1] = 0, 不需要匹配。
for (int i = 2, j = 0; i <= n; i ++ )
{
while (j && p[i] != p[j + 1]) j = ne[j]; //当j不为0 且下一个字符不匹配时,j回到与它匹配的位置,求次长,
//若一直不匹配则j = 0跳出循环,另一种跳出循环的情况就是下一个字符匹配成功。
if (p[i] == p[j + 1]) j ++ ; //来到这里j有两种情况(0和非0),当j==0, 意味接下来用模式串的第一个字符来匹配,成功就加1,失败不加
//当j!=0, 意味着模式串已经成功匹配j个长度了,而且从上面的循环跳出条件看,下一个字符一定是匹配的,j一定加1
ne[i] = j; //当j!=0,j已经加1,ne[i]成功匹配的长度就为j。若上面j == 0,下个字符相同,ne[i]匹配长度就为1,否则为0
}
//kmp过程,和求ne数组大同小异,求ne数组相当于自己与自己匹配,kmp是两个不同的字符串模式匹配
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);//返回起始地点,终点是i,长度是n,起点是i - n + 1, 因为s下标从1开始的,所以我们要-1,i-n+1-1=i-n
j = ne[j]; //再次缩短长度进行下一次的匹配,辛苦了,加油!
}
}
return 0;
}