1. 程式人生 > >hdu 5918 Sequence I

hdu 5918 Sequence I

!= define () kmp alt 個數 font scan 技術

給兩個數組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; }
View Code

hdu 5918 Sequence I