國慶七天樂day1_2016中國大學生程式設計競賽(長春)hdu5918_Sequence I(kmp)
阿新 • • 發佈:2018-12-12
題意:問a從存在多少子序列滿足子序列在a中的下標間隔為p且該子序列就是b.
直接把個子序列拿出來,依次kmp求和即可,每次詢問複雜度為
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e6+5; int a[maxn],b[maxn],s[maxn]; int Next[maxn]; int n,m,p; void getnext() { int k=0; Next[0]=0; for(int q = 1; q < m; q++) { while(k>0&&b[q]!=b[k]) k=Next[k-1]; if(b[q]==b[k]) k++; Next[q]=k; } } int kmp(int len) { int ans=0,k=0; if(len<m) return 0; for(int p=0;p<len;p++) { while(k&&s[p]!=b[k]) k=Next[k-1]; if(s[p]==b[k]) k++; if(k==m) ans++,k=Next[k-1]; } return ans; } int main() { int t,cnt=0; scanf("%d",&t); while(t--) { cnt++; scanf("%d%d%d",&n,&m,&p); for(int i=0; i<n; i++) scanf("%d",&a[i]); for(int i=0; i<m; i++) scanf("%d",&b[i]); getnext(); ll ans=0; for(int i=0;i<p;i++) { int pos=0; for(int j=i;j<n;j+=p) s[pos++]=a[j]; ans+=kmp(pos); } printf("Case #%d: %lld\n",cnt,ans); } }