我是靠谱客的博主 微笑大侠,最近开发中收集的这篇文章主要介绍hdu5918-Sequence I (kmp),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目来源:http://./showproblem.php?pid=5918

题意

给出一个a序列,b序列,然后问在a序列中有多少个b序列,并且是以下形式:
b1,b2,⋯,bmb1,b2,⋯,bm is exactly the sequence aq,aq+p,aq+2p,⋯,aq+(m−1)paq,aq+p,aq+2p,⋯,aq+(m−1)p where q+(m−1)p≤nq+(m−1)p≤n and q≥1。

思路

按照最暴力的方法,枚举一个个位置,从左至右,共n-(m-1)*p个。
但是极限数据会是O(n²)的时间复杂度,需要优化。
想到了kmp,手打一套,记一下数,就可以了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=1e6+10;
LL a[maxn],b[maxn],nexx[maxn];
int n,m,p;
void next_()
{
    memset(nexx,0,sizeof(nexx));
    int j=-1,i=0;
    nexx[0]=-1;
    while(i<m)
    {
        if(j==-1||b[j]==b[i])
        {
            nexx[++i]=++j;
        }
        else
        j=nexx[j];
    }
}
int kmp_(int pos)
{
    int i=pos,j=0,ans=0;
    while(i<n&&j<m)
    {
        if(j==-1||a[i]==b[j])
        {
            i+=p;
            j++;
        }
        else
           j=nexx[j];
        if(j>=m)
        {
            ans++;
            j=nexx[j];
        }
    }
    return ans;
}
int main()
{
    int T,cases=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        for(int i=0; i<n; i++)
            scanf("%lld",&a[i]);
        for(int i=0; i<m; i++)
            scanf("%lld",&b[i]);
        next_();
        int res=n-(m-1)*p;
        int ans=0;
        for(int i=0; i<p&&i<res; i++)
        {
            ans+=kmp_(i);
        }
        printf("Case #%d: %dn",cases++,ans);
    }
}

最后

以上就是微笑大侠为你收集整理的hdu5918-Sequence I (kmp)的全部内容,希望文章能够帮你解决hdu5918-Sequence I (kmp)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部