前提技能:前缀数组
参考博客:KMP算法(kuangbin)
const int maxn=1e5; int Next[maxn]; /*求前缀数组*/ /*t[0]对应Next[1]*/ /*Next[0]=-1*/ void getNext(string t) { int i=0,j=-1,n=t.length(); Next[0]=-1; while(i<n) { if(j==-1||t[i]==t[j]) Next[++i]=++j; else j=Next[j]; } } /*求 t 在 s 中出现的次数(可交叉)(即:s="bababa" t="baba" KMP_count()=2)*/ int KMP_count(string s,string t) { int ans=0,slen=s.length(),tlen=t.length(); if(slen==1&&tlen==1) { if(s==t) return 1; else return 0; } getNext(t); for(int i=0,j=0;i<slen;++i) { while(j>0&&s[i]!=t[j]) j=Next[j]; if(s[i]==t[j]) j++; if(j==tlen) ans++,j=Next[j]; } return ans; } /*求 t 在 s 中出现的第一个位置(从0开始数)*/ int KMP_index(string s,string t) { int i=0,j=0,slen=s.length(),tlen=t.length(); getNext(t); while(i<slen&&j<tlen) { if(j==-1||s[i]==t[j]) i++,j++; else j=Next[j]; } if(j==tlen) return i-tlen; else return -1; }