KMP
太简单了
考场现推吧
就是一个
n
e
x
t
next
next数组
n
e
x
t
i
next_i
nexti表示前缀字符串
s
t
[
1...
i
]
st[1...i]
st[1...i]存在的一个最大的前缀字符串
s
t
[
1....
j
]
st[1....j]
st[1....j]使得
s
t
[
1....
j
]
=
s
t
[
i
−
j
+
1......
i
]
st[1....j] = st[i - j + 1 ...... i]
st[1....j]=st[i−j+1......i]
然后就没了
code:
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int a[N], nxt[N];
char st[N], st1[N];
int main(){
scanf("%s", st + 1);
scanf("%s", st1 + 1);
int len1 = strlen(st + 1), len2 = strlen(st1 + 1);
int j = 0;
for(int i = 1; i < len2; i ++){//因为是后缀的最大前缀,所以要错开一位,从1开始循环,2开始建nxt
while(j && st1[j + 1] != st1[i + 1]) j = nxt[j];//匹配不到就往前跳
j += (st1[j + 1] == st1[i + 1]);
nxt[i + 1] = j;
}
j = 0;
for(int i = 0; i < len1; i ++){//匹配
while(j && st1[j + 1] != st[i + 1]) j = nxt[j];
j += (st1[j + 1] == st[i + 1]);
if(j == len2) a[++ a[0]] = i + 1 - j + 1, j = nxt[j];
}
for(int i = 1; i <= a[0]; i ++) printf("%d\n", a[i]);// printf("\n");
for(int i = 1; i <= len2; i ++) printf("%d ", nxt[i]);
return 0;
}