当kmp在母串中匹配到子串之后,删去子串相当于把失配指针往回退到匹配位置的前一个,如果只回退一次的话,直接用数组就可以处理失配指针了,但是本题可能删除后存在多个子串,所以用栈把失配指针位置先存起来,然后找到一次把len长度的失配指针删去,然后栈顶元素就是第一句话说的回退出匹配位置的前一个了。
为了方便调用函数,把以前的kmp改成了接口,方便使用,这样就不用开全局变量的数组了,代码看起来更符合工作中开发的代码风格。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define sc(a,b) scanf("%d%d",&a,&b)
#define pri(a) printf("%d\n",a)
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define MM 400005
#define MN 100005
#define INF 1000000007
#define eps 1e-7
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
void fail(char *ss,int *next)
{
int k=-1,j=0,len=strlen(ss);
next[0]=-1;
while(j<len)
{
if(k==-1||ss[j]==ss[k])
{
j++,k++;
if(ss[j]!=ss[k]) next[j]=k;
else next[j]=next[k];
}
else k=next[k];
}
}
int kmp(char *substr,char *str)
{
stack<int>s;
int next[260];
fail(substr,next);
int i=-1,j=-1,sum=0;
int len=strlen(str),lensub=strlen(substr);
while(i<len)
{
if(j==-1||substr[j]==str[i])
{
i++,j++,s.push(j);
if(j==lensub)
{
sum++;
for(int ii=0; ii<lensub; ii++) s.pop();
j=s.top();
}
}
else j=next[j];
}
return sum;
}
int main()
{
static char substr[270],str[510005];
while(~scanf("%s%s",substr,str))
{
pri(kmp(substr,str));
}
return 0;
}