Top

KMP模板及优化


解决问题:字符串匹配。给你两个字符串,寻找其中一个字符串是否包含另一个字符串,如果包含,返回包含的起始位置。 或者给你两个字符串,查找一个字符串在另外一个字符串中出现了几次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include<bits/stdc++.h>
using namespace std;
const int maxn=10001;
int next[maxn];
char s[maxn];
char p[maxn];
int cnt=0;
void prefix_next(int n){
next[0]=0;
int len=0;
int i=1;
while(i<n){
if(p[i]==p[len]){
len++;
next[i]=len;
}
else {
if(len>0){
len=next[len-1];
}
else{
next[i++]=len;
}
}
}
return;
}
void move_next(int n){
for(int i=n-1;i>0;i--){
next[i]=next[i-1];
}
next[0]=-1;
return;
}
void kmp_search(){
int n=strlen(p);
int m=strlen(s);
prefix_next(n);
move_next(n);
int i=0;
int j=0;
while(i<m){
if(s[i]==p[j]&&j==n-1){
printf("No.%d-->%d\n",++cnt,i-j);
j=next[j];
}
if(s[i]==p[j]){
i++;
j++;
}
else{
j=next[j];
if(j==-1){
i++;j++;
}
}
}
if(cnt==0)cout<<"NO FOUD"<<endl;
return;
}
int main(){
cin>>s;
cin>>p;
kmp_search();
}

KMP优化模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
char s[1000005],t[200000];
int slen,tlen;
int nex[200000];//nex数组大小和短串一致
int ans,a,b,c,d,n,m;
inline void get_nex()
{
int j=-1;//j初始化为-1
for (int i=0;i<tlen;i++){
while (t[i]!=t[j+1] && j!=-1)//如果下一个不同,那么j就变成next[j],注意next[j]是小于j的,无论j取任何值
j=nex[j];//往前回溯
if (t[i]==t[j+1] && i!=0) j++;//如果相同,j++
nex[i]=j;//这个是把算的j的值(就是相同的最大前缀和最大后缀长)赋给next[i]
}
}
inline void kmp()
{
int j=-1;
for (int i=0;i<slen;i++){
while (s[i]!=t[j+1] && j!=-1)
j=nex[j];
if (s[i]==t[j+1])
j++;
if (j==tlen-1)
ans++,j=nex[j];
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++){
ans=0;
scanf("%s %s",t,s);
slen=strlen(s);
tlen=strlen(t);//这两个长度应该设为全局变量最开始时求出,不能用一次求一次
get_nex();
kmp();
printf("%d\n",ans);
}
}


未经允许不得转载: Anoyer's Blog » KMP模板及优化