概述
题目来源: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)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复