给两个数组a , b,并给一个间隔值p。问在间隔值p下b在中有多少个匹配。
比如a数组为1 2 2 4 3,b数组为1 2 3,那么在间隔值为2的情况下有一个匹配。
把a数组中可以作为开头的所有间隔数字比如2可以开头的数字是1或者2,3可以开头的数字是1、2、3取出来。
然后做p次kmp即可。
//#define test #include<bits/stdc++.h> using namespace std; const int Nmax=2e6+7; int f[Nmax]; int flag[Nmax]; inline void init(int *s,int m) { f[0]=f[1]=0; for(int i=1; i<m; i++) { int j=f[i]; while(j && s[i]!=s[j]) j=f[j]; f[i+1] = s[i] == s[j] ? j + 1 : 0; } } inline int get(int *s,int *t,int m,int n) { int ans=0; for(int i=0,j=0; i<n; ++i) { while(j && t[i]!=s[j]) j=f[j]; j+=(t[i]==s[j]); if(j==m) { //printf("\n now: %d\n",i-m+1); ans++; j=f[j]; } } return ans; } int s[Nmax],t[Nmax]; int m,n; int p; int a[Nmax],b[Nmax]; int main() { #ifdef test #endif int tt; //freopen("h.in","r",stdin); scanf("%d",&tt); for(int cases=1;cases<=tt;cases++) { printf("Case #%d: ",cases); scanf("%d%d%d",&m,&n,&p); for(int i=1;i<=m;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); for(int i=0;i<n;i++) t[i]=b[i+1]; //printf("%s\n",t); //t[n]=‘\0‘; int ans=0; for(int i=0;i<=m+1;i++) flag[i]=0; init(t,n); //if(m<p) //{ //if(n==1) //{ //for(int i=1;i<=m;i++) //if(a[i]==b[1]) //ans++; //} //printf("%lld\n",ans); //continue; //} int flagnow=0; for(int now=1;now+(n-1)*p<=m;now++) { int ttt=0; for(int i=now;i<=m;i+=p) { if(flag[i]) { flagnow=1; break; } s[ttt++]=a[i]; flag[i]=1; } if(!ttt || flagnow) break; if(ttt<n) break; //s[ttt]=‘\0‘; //printf("%s",s); //init(ttt); //printf("g:%d\n",get(t,s,n,ttt)); ans+=get(t,s,n,ttt); } printf("%d\n",ans); } return 0; }
原文地址:https://www.cnblogs.com/LMissher/p/9673944.html
时间: 2024-10-20 00:41:27