JZOJ 5437. 【NOIP2017提高A组集训10.31】Sequence

来源:互联网 发布:单片机原理图设计 编辑:程序博客网 时间:2024/06/05 20:15

题目

这里写图片描述

题解

可以想象一下两个函数图像,就是问有几段长度为m的,a函数往下平移一个常数与b函数重合。
问题转化为:差分之后,有多少条连续m个元素的序列和另一个序列完全一样。
上一波KMP,b[i]b[i1]作为模式串,a[i]a[i1]作为匹配串。
记得KMP匹配到m之后,就当匹配失败,此时j=next[j]。

代码

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#define N 1000010#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;int i,j,k,l,n,m,ans;int a[N],b[N];int p[N],s[N],t[N];int read(){    int res=0,fh=1;char ch;    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();    if(ch=='-')fh=-1,ch=getchar();    while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();    return res*fh;}int main(){    n=read(),m=read();    fo(i,1,n)a[i]=read();    fo(i,1,m)b[i]=read();    fo(i,2,n)s[i-1]=a[i]-a[i-1];    fo(i,2,m)t[i-1]=b[i]-b[i-1];    p[1]=0;j=0;    fo(i,2,m-1){        while(j&&t[j+1]!=t[i])j=p[j];        if(t[j+1]==t[i])j++;        p[i]=j;    }    j=0;    fo(i,1,n-1){        while(j&&t[j+1]!=s[i])j=p[j];        if(t[j+1]==s[i])j++;        if(j==m-1)ans++,j=p[j];    }    printf("%d",ans);    return 0;}