KMP
这个算法非常妙,妙极了;
具体内容可以看此处就不多赘述了
如果想自学的请点击下列链接本篇只是我自己写写记记的
看毛片算法
模板题
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define int long long
#define debug puts("FUCK")
const int N=1000010;
int f[N],n,m,nexxt[N]; char a[N],b[N];
signed main()
{
cin >> (b+1); cin >> (a+1);//解释一下这里为什么用cin因为能
//过滤空格回车方便的很,a+1是从char数组的1号格子开始存放东西
m = strlen(b+1); n = strlen(a+1);
//接下来这步表示从自身去寻找前缀和后缀的最大子串
for (int i = 2, j = 0; i <= n; i ++ ){
while (j > 0 && a[i] != a[j+1]) j = nexxt[j];//调用自己来寻找自己和自己的子串
if (a[i] == a[j+1]) j ++ ;//继续
nexxt[i] = j;//这句话也非常重要
//转载博客里说这个循环其实就是找前面和后面相同的部分,nexxt[i] = j;,就是将
//前后重合的部分一一对应,这样子的话呢,在下面一个循环就可以直接后面如果不匹配了
}
for (int i = 1, j = 0; i <= m; i ++ ){
while (j >0 && (j == n || b[i] != a[j+1])) j = nexxt[j];//这部非常关键,因为
//如果后面不匹配了就折回到前面继续进行匹配,相当于把模式串往后挪了很多位,加快了进程
//这里就是和暴力的主要区别
if (b[i] == a[j+1]) j ++ ;
f[i] = j;
if (f[i] == n) printf("%lld\n", i-n+1), j = nexxt[j];
}
for(int i = 1; i <= n; i++){
printf("%lld ",nexxt[i]);
}
return 0;
}