欢迎点赞,评论。
题目:https://www.luogu.com.cn/problem/P3375
![](https://i-blog.csdnimg.cn/blog_migrate/1cec1c063fec6f70152e1c7625c9e574.png)
第一次匹配成功之后 j 的位置 回溯到 ne[] 数组记录的前面已经匹配的长度(第一次匹配成功
则前三个字母ABA一定是匹配的 所以 j 回溯到A所在的位置 此时比对的是 j + 1)
定义一个字符串s的 border 为s的一个非 s本身的子串 t,满足t既是s的 前缀,又是s的 后缀。
最后一行输出 |s2|个整数,第 i个整数表示s2的长度为 i的前缀的最长 border 长度。
理解为s的每个 从前自后 每次在末尾增加一个字母的 子串
例:BABABAC 即 B BA BAB BABA ...
![](https://i-blog.csdnimg.cn/blog_migrate/6b9f8ddb0931cb5b0b6da95e5671c2d0.png)
border 即s2每个子串的最长公共前后缀 ➡ ne[]数组
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
char s[N],p[N];
int ne[N];
int main()
{
cin >> s + 1;
cin >> p + 1;
int n = strlen(s + 1),m = strlen(p + 1);
// ne[]数组
for(int i = 2,j = 0;i <= m;i++)
{
while(j && p[i] != p[j + 1]) j = ne[j];//同KMP匹配过程
if(p[i] == p[j + 1]) j++;
ne[i] = j; // 不同的是 每次移动i前 将i前面已经匹配的长度记录到ne[]数组中
}
for(int i = 1,j = 0;i <= n;i++) // 从 1 开始
{
while(j && s[i] != p[j + 1]) j = ne[j];
if(s[i] == p[j + 1]) j++; // j 是指针
if(j == m)
{
cout << i - m + 1 << endl; //指针 j 指的是往后一位 所以 i - m + 1 就是第几位
j = ne[j];
}
}
for(int i = 1;i <= m;i++) cout << ne[i] << ' ';
return 0;
}