学习KMP之旅:
博客:https://blog.csdn.net/v_july_v/article/details/7041827
视频:https://www.bilibili.com/video/av11866460?from=search&seid=12373536177229719887
然后就是上代码:
#include <cstdio>
#include <cstring>
const int N = 1000010 ;
char a[N] , b[N] ;
int pre[N] ;
void kmp(){
int n = strlen(a) ;
int m = strlen(b) ;
int k = 1 , len = 0 ;
pre[0] = 0 ;
//寻找公共前后缀长度 (dp)
while(k < m){
if (b[k] == b[len]){//如果当前字符等于len所指的字符,则最长公共前后缀长度加一
++ len ;
pre[k] = len ;
++ k ;
}
else{
if (len > 0) //如果不相等,则找到不相等的前一位的pre值
len = pre[len - 1] ;
else{
pre[k] = len ;
++ k ;
}
}
}
//最长前后缀长度的数组往后移动一位,第一位赋值为-1(标明七点)
for (k = m ; k > 0 ; --k)
pre[k] = pre[k-1] ;
pre[0] = -1 ;
// i , a[i] , n
// j , b[j] , m
int j = 0 , i = 0 ;
while(i < n){
if (j == m-1 && a[i] == b[j]){
printf ("%d\n",i-j+1) ;
j = pre[j] ;
}
if (a[i] == b[j]){
++ i ;
++ j ;
}
else{
j = pre[j] ;
if (j == -1){
++ i ;
++ j ;
}
}
}
for (int k = 1 ; k <= m ; k ++){
printf ("%d ",pre[k]) ;
}
}
int main(){
scanf ("%s",a) ;
getchar() ;
scanf ("%s",b) ;
kmp() ;
return 0 ;
}