2264: sequence
时间限制: 1 Sec 内存限制: 128 MB提交: 407 解决: 52
[ 提交][ 状态][ 讨论版][命题人: admin]
题目描述
给定一个含n个数的序列A和一个含m (m<=n) 个数的序列B。
询问在A中有多少段连续的长为m的子序列Ak,Ak+1,…,Ak+m-1使得对于任意1<=i, j<=m满足Ak+i-1-Bi=Ak+j-1-Bj
输入
第一行两个整数n,m (1 <= m <= n <= 106)
接下来一行n个整数,描述序列A (Ai <= 109)
接下来一行m个整数,描述序列B (Bi <= 109)
输出
输出一个数表示答案
样例输入
7 46 6 8 5 5 7 47 7 9 6
样例输出
2
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int MAX = 1e6+10;
const int INF = 0x3fffffff;
int n,m;
int Next[MAX];
int t[MAX];
int a[MAX];
int b[MAX];
//求next 数组
void get_next(){
int j=-1,i=0;
Next[0] = -1;
while(i<m){
if(j==-1||b[i]==b[j]) {
j++;
i++;
Next[i] = j;
}
else
j = Next[j];
}
}
//KMP函数返回匹配成功个数
int KMP(){
int i,j;
int ans=0;
i=j=0;
while(i<n) {
while(-1!=j && a[i]!=b[j])
j=Next[j];
i++; j++;
if(j >= m){
ans++;
j=Next[j];
}
}
return ans;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(t,0,sizeof(t));
for(int i=0;i<n;i++){
scanf("%d",&t[i]);
}
for(int i=0;i<n-1;i++){
a[i] = t[i+1]-t[i];
}
n--;
memset(t,0,sizeof(t));
for(int i=0;i<m;i++){
scanf("%d",&t[i]);
}
for(int i=0;i<m-1;i++){
b[i] = t[i+1]-t[i];
}
m--;
get_next();
int ans = KMP();
cout<<ans<<endl;
}
return 0;
}