HDU 5918 Sequence I

题目来源:2016 CCPC 长春站
题意:给出两个序列 a[] , b[] ,如果b1,b2....bm能够与aq,aq+p,aq+2p...aq+(m-1)p对应( q+(m-1)p<=n && q>=1 ),则q为一个合法的数,找出满足题意的q的个数
思路:简单KMP,枚举起点q,如果匹配成功后记录一次然后重新从最后匹配位置进行匹配,一直匹配到a[]结束

/*************************************************************************
    > File Name: C.cpp
    > Author:    WArobot 
    > Mail:      768059009@qq.com 
    > Created Time: 2017年04月15日 星期六 21时11分01秒
 ************************************************************************/

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1000000+10;
int n,m,p,ans,t;
int a[maxn],b[maxn];
int _next[maxn];

void get__next(){
	int plen = m;
	_next[0] = -1;
	int k = -1 , j = 0;
	while(j<plen){
		if(k==-1 || b[j]==b[k])	 j++ , k++ , _next[j] = k;
		else k = _next[k];
	}
}
int Kmpserch(int q){
	int i = q , j = 0;
	int k = 0;
	while(i<n && j<m){
		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 kase=0;
	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 j=0;j<m;j++)	scanf("%d",b+j);
		get__next();
		for(int q = 0;q<n && q<p ;q++){
			ans += Kmpserch(q);
		}
		printf("Case #%d: %d
",++kase,ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/WArobot/p/6723663.html