我是靠谱客的博主 微笑大侠,这篇文章主要介绍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,手打一套,记一下数,就可以了。

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#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内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部