当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; }
ZOJ 3643 kmp+栈处理失配指针,布布扣,bubuko.com
时间: 2024-10-11 06:26:30