题意:已知序列A和序列B以及p,问有多少个位置q,使得b1,b2,…,bm与恰好匹配。
KMP算法稍作修改即可,next数组部分是不需要修改的,只需要改一下匹配过程,当序列A中的a[i]等于序列B中的b[j]时,将原先的i++改为i+=p即可。
代码:
#include <bits/stdc++.h>
using namespace std;
const int max_n=1e6+5;
int next[max_n],a[max_n],b[max_n];
int n,m,p;
void getnext()
{
int i=0,j=-1;
next[0]=-1;
while(i<m)
{
if(j==-1||b[i]==b[j])
next[++i]=++j;
else
j=next[j];
}
}
int kmp(int index)
{
int i=index,j=0,k=0;
while(i<n)
{
if(j==-1|a[i]==b[j])
i+=p,j++;
else
j=next[j];
if(j==m)
k++,j=next[j];
}
return k;
}
int main()
{
int t,ans,Case=1;
scanf("%d",&t);
while(t--)
{
ans=0;
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();
for(int i=0;i<p&&i<n;i++)//避免重复枚举i<p,当然i<n
ans+=kmp(i);
printf("Case #%d: %d\n",Case++,ans);
}
return 0;
}