char a[1000006];//原串
char p[1000006];//子串
int pmt[1000006];
void getNext(int m){
int j=0;
pmt[0]=0;
for(int i=1;i<m;++i){
while(j>0 && p[i]!=p[j])
j=pmt[j-1];
if(p[i]==p[j])
++j;
pmt[i]=j;
}
}
以下实例基于上述getNext函数及数据结构执行:
下例代码中,n为原串a长度,m为子串p长度。以原串第一个字母为下标‘0’位置。
void kmp_findstr(int n,int m){
getNext(m);
for(int i=0,j=0;i<n;i++){
while(j && a[i]!=p[j])
j=pmt[j-1];
if(a[i]==p[j])
++j;
if(j==m){
cout<<i-j+1<<endl;
j=pmt[j-1];
}
}
}
函数返回原串第一次匹配子串的位置,如果不匹配则返回-1。
int kmp_findfirst(int n,int m){
int place=-1;
getNext(m);
for(int i=0,j=0;i<n;++i){
while(j>0 && p[j]!=a[i])
j=pmt[j-1];
if(p[j]==a[i])
++j;
if(j==m){
place=i-m+1;
break;
}
}
return place;
}
int kmp_strcount(int n,int m){
int i,j=0,res=0;
getNext(m);
for(i=0;i<n;++i){
while(j>0 && p[j]!=a[i])
j=pmt[j-1];
if(p[j]==a[i])
++j;
if(j==m)
++res;
}
return res;
}
PS: 力扣周赛最后一题用到KMP了,直接AC。
顺便附上源代码:
class Solution {
private:
char num[1000006];
char p[1000006];
int kmp_next[1000006];
void getNext(int m){
int j=0;
kmp_next[0]=0;
for(int i=1;i<m;++i){
while(j>0 && p[i]!=p[j])
j=kmp_next[j-1];
if(p[i]==p[j])
++j;
kmp_next[i]=j;
}
}
int kmp(int n,int m){
int i,j=0,res=0;
getNext(m);
for(i=0; i<n; ++i){
while(j>0 && p[j]!=num[i])
j=kmp_next[j-1];
if(p[j]==num[i])
++j;
if(j==m)
++res;
}
return res;
}
public:
int countMatchingSubarrays(vector<int>& nums, vector<int>& pattern) {
int n=nums.size(),m=pattern.size();
for(int i=0;i<n-1;i+=1){
if(nums[i+1]>nums[i])
num[i]='a';
else if(nums[i+1]==nums[i])
num[i]='b';
else if(nums[i+1]<nums[i])
num[i]='c';
}
num[n-1]='d';
for(int i=0;i<m;i+=1){
if(pattern[i]==1)
p[i]='a';
else if(pattern[i]==0)
p[i]='b';
else if(pattern[i]==-1)
p[i]='c';
}
int res=kmp(n,m);
return res;
}
};