题目大意:

给你两个数组 a,b。还有一个间隔长度 t 。现在让你找 a 数组以长度 t 为间隔,里面有多少个 b 。

分析:

以 t 为间隔将 a 数组分成几个子序列,然后每个子序列分别与 b 进行匹配,用 kmp 。
后经测试发现,这道题直接暴力枚举也是可以过的。两个方法的代码都贴一下吧。

代码:

暴力枚举:608ms

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
#define maxn 1000500
int n,m,t;
int a[maxn],b[maxn];
int main()
{
    int T;
    int test=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&t);
        test++;
        int s=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m;i++)//b作为模式串去和他们匹配 
        {
            scanf("%d",&b[i]);
        }
        int end=n-t*(m-1);
        for(int i=1;i<=end;i++)
        {
            int flag=1;
            for(int j=1;j<=m;j++)
            {
                if(b[j]!=a[i+(j-1)*t])
                {
                    flag=0;
                    break;
                }
            }
            if(flag==1)s++;
        }
        printf("Case #%d: %d\n",test,s);
    }
}

KMP匹配优化:608ms 真的没骗你,我可能是用了假的kmp~

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
#define maxn 1000500
int n,m,t;
int a[maxn],b[maxn];
int Next[maxn];
int c[maxn];//按间隔提取出的a的子序列 

void get_Next()
{
    Next[0]=-1;
    int k=-1,i=0;
    while(i<m)
    {
        if(k!=-1&&b[i]!=b[k])
        {
            k=Next[k];
            continue;
        }
        k++;i++;
        if(i==m)
        {
            Next[i]=k;
            break;
        }
        if(b[i]!=b[k])Next[i]=k;
        else Next[i]=Next[k];
    }
}

int match(int numc)
{
    int s=0;
    int i=0,j=0;
    while(1)
    {
        if(i>=numc&&j<m)break;
        if(j==m||c[i]!=b[j])
        {
            if(j==m)s++;
            j=Next[j];
            if(j==-1)
            {
                j++;i++;
            }
            continue;
        }
        i++;j++;
    }
    return s;
}

int main()
{
    int T;
    int test=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&t);
        test++;
        int s=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=0;i<m;i++)//b作为模式串去和他们匹配 
        {
            scanf("%d",&b[i]);
        }
        /*int end=n-t*(m-1);
        for(int i=1;i<=end;i++)
        {
            int flag=1;
            for(int j=1;j<=m;j++)
            {
                if(b[j]!=a[i+(j-1)*t])
                {
                    flag=0;
                    break;
                }
            }
            if(flag==1)s++;
        }*/
        get_Next();
        for(int i=0;i<t;i++)
        {
            int numc=0;//c数组元素个数 
            int j=i;
            while(1)
            {
                c[numc]=a[j];
                numc++;
                j+=t;
                if(j>=n)break;
            }
            if(numc>=m)s+=match(numc);
            //cout<<numc<<endl;
        }
        printf("Case #%d: %d\n",test,s);
    }
}