KMP算法
题目描述
给定两个字符串str和match,长度分别为N和M。实现一个算法,如果字符串str中含有子串match,则返回match在str中的开始位置,不含有则返回-1
若出现了多次,则按照升序输出所有出现位置
[要求]
时间复杂度为 O ( n ) O(n) O(n)
输入描述:
第一行一个字符串str
第二行一个字符串match
输出描述:
输出若干个数,分别为match在str中出现的位置,从0开始标号。
若不存在输出-1
示例1
输入
acbc
bc
输出
2
示例2
输入
acbc
bcc
输出
-1
示例3
输入
ababab
ab
输出
0 2 4
备注:
1
⩽
l
e
n
g
t
h
(
s
t
r
)
,
l
e
n
g
t
h
(
m
a
t
c
h
)
⩽
5
∗
1
0
5
1 \leqslant length(str),length(match) \leqslant 5∗10^5
1⩽length(str),length(match)⩽5∗105
保证字符集为小写字母
题解:
KMP 模板题,在理解 KMP 核心思想下,背模板即可,不然现场写这个算法还是有点难度。。。
代码:
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 500001;
char s[N], p[N];
int n, m;
int ne[N];
int main(void) {
scanf("%s", s + 1);
scanf("%s", p + 1);
n = strlen( s + 1 );
m = strlen( p + 1 );
for ( int i = 2, j = 0; i <= m; ++i ) {
while( j && p[i] != p[j + 1] ) j = ne[j];
if ( p[i] == p[j + 1]) ++j;
ne[i] = j;
}
bool flag = false;
for ( int i = 1, j = 0; i <= n; ++i ) {
while ( j && s[i] != p[j + 1] ) j = ne[j];
if ( s[i] == p[j + 1] ) ++j;
if ( j == m) {
flag = true;
printf("%d ", i - m);
j = ne[j];
}
}
if ( !flag ) printf("-1 ");
return 0 * puts("");
}