最近复习了一下集训学的kmp算法。
kmp算法可以将字符串匹配的时间复杂度由
O(n2)
O
(
n
2
)
降低到
O(nlogn)
O
(
n
l
o
g
n
)
,还有各种神奇的用途。
对于求一个串是否是另一个串的子串,可以先求出一个数组next[i],表示1到i中前缀等于后缀的长度。
然后kmp算法就是充分利用之前已知的数据,如果第i-1位的next数组是
next[i−1]
n
e
x
t
[
i
−
1
]
,那么对于第i个数,如果第i位与第next[i-1]+1位相同,那么就将next[i]赋值为next[i-1]+1.
如果没有成功配对,那么就找第next[next[i]]位的,如图
代码
//Writer:jr HSZ;%%%WJMZBMR
#include<bits/stdc++.h>
#define LL long long
#define reg register int
#define f(i,a,b) for(reg i=a;i<=b;i++)
using namespace std;
char tp[1000001],s[1000000*2+1];
int nxt[1000001*2];
int len,lent,len2;
void kmp() {
int j=0;
for(int i=2; i<=len; i++) {
while(j>0&&s[i]!=s[j+1])
j=nxt[j];
if(s[i]==s[j+1])j++;
nxt[i]=j;
if(nxt[i]==len2&&i>len2+1)cout<<i-(len2)*2<<endl;
}
}
int main() {
cin>>tp+1;
lent=strlen(tp+1);
cin>>s+1;
len2=strlen(s+1);
s[len2+1]='*';
for(int i=len2+2; i<=lent+len2+2; i++)s[i]=tp[i-len2-1];
len=strlen(s+1);
kmp();
for(int i=1; i<=len2; i++)cout<<nxt[i]<<" ";
cout<<endl;
return 0;
}
睡觉ZZZ