//KMP算法实现,参照ACM模板
//牛客网,上海交通大学机试题
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e6+7;
char P[maxn],T[maxn];
int Next[maxn];
void preKmp(char P[],int m,int Next[]){
int i=0,j=-1;
Next[0]=-1;
while(i<m){
while(j!=-1&&P[i]!=P[j]) j=Next[j];
if(P[++i]==P[++j]) Next[i]=Next[j];
else Next[i]=j;
}
}
int KMP_Count(char P[],int m,char T[],int n){
//P是模式串,T是主串
int i=0,j=0;
int ans=0;
preKmp(P,m,Next);
while(i<n){
while(j!=-1&&T[i]!=P[j])
j=Next[j];
++i;++j;
if(j>=m){
ans++;
j=Next[j];
}
}
return ans;
}
int main(){
cin>>T>>P;
int ans=KMP_Count(P,strlen(P),T,strlen(T));
cout<<ans<<endl;
return 0;
}
更新 2020/3/19
参考算法导论
public class Main {
static int[] next;
public static void main(String[] args) throws Exception {
String p = "ababa";
String s = "bacbababaabcbab";
System.out.println(KMP_Count(p, s));
}
static int KMP_Count(String p, String s) {
int[] pi = computePrefix(p);
int n = s.length();
int m = p.length();
int cnt = 0;
int q = -1;
for (int i = 0; i < n; ++i) {
while(q != -1 && p.charAt(q+1) != s.charAt(i)) q = pi[q];
if (p.charAt(q+1) == s.charAt(i)) q++;
if (q == m - 1) { // 匹配
cnt++;
q = pi[q];
}
}
return cnt;
}
static int[] computePrefix(String p) {
int m = p.length(); // 有效偏移s,模式串长m,已匹配q个字符,q的最长真前缀和最长真后缀匹[0,k]
int[] pi = new int[m];
pi[0] = -1;
int k = -1;
for (int q = 1; q < m; ++q) {
while(k != -1 && p.charAt(k + 1) != p.charAt(q)) k = pi[k];
if (p.charAt(k+1) == p.charAt(q)) k++;
pi[q] = k;
}
return pi;
}
}