2017年浙江工业大学大学生程序设计迎新赛决赛—网络同步赛 E-栗酱的数列(KMP)

来源:互联网 发布:html外链js 编辑:程序博客网 时间:2024/04/30 02:07

题目描述

栗酱有一个长度为n的数列A,一个长度为m的数列B,现在询问A中有多少个长度为m的连续子序列A',
满足(a'1+b1)%k = (a'2+b2)%k = …… = (a'm + bm)%k。

输入描述:

第一行一个数T,表示有T组数据。
对于每组数据,
第一行三个整数,n, m, k。
第一行输入n个数, a1,a2,…,an, 表示A数列中的数,
第二行输入m个数, b1,b2,…,bm, 表示B数列中的数。

输出描述:

每一组数据输出一行,满足条件的连续子序列数量。
示例1

输入

23 2 57 8 78 73 2 57 8 98 7

输出

12

备注:

T≤15,
2≤m≤n≤2×105,
1≤ai,bi,k≤109

由(a'1+b1)%k = (a'2+b2)%k = …… = (a'm + bm)%k转换一下


(a1+b1)%k=(a2+b2)%k



(a2+b2a1b1)%k=0

((a2a1)+(b2b1))%k=0

(a2+b2a1b1)%k=0那么

那么只需要存一下da[i]=a[i+1]-a[i]和db[i]=b[i+1]-a[i]

修改一下KMP的条件,让da匹配db即可

过程:对db求next数组,用da匹配db,把匹配时的判断改为(da[i]+db[i])%k==0

#include<bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))using namespace std;typedef long long ll;const int N=2e5+50;int nxt[N],a[N],b[N];int da[N],db[N];int n,m,k,t;void get_nxt(){    int i=0,j=-1;    nxt[0]=-1;    while(i<m)    {        if(j==-1||db[i]==db[j])        {            nxt[++i]=++j;        }        else            j=nxt[j];    }}void kmp(){    get_nxt();    int ans=0,i=0,j=0,la=n,lb=m;    while(i<la)    {        if(j==-1||(da[i]+db[j])%k==0)        {            ++i,++j;        }        else            j=nxt[j];        if(j==lb)ans++,j=nxt[j];    }    printf("%d\n",ans);}int main(){    scanf("%d",&t);    while(t--)    {     scanf("%d%d%d",&n,&m,&k);     for(int i=0;i<n;i++)        {            scanf("%d",&a[i]);            a[i]%=k;        }     for(int i=0;i<m;i++)        {            scanf("%d",&b[i]);            b[i]%=k;        }    for(int i=0;i<n-1;i++)        da[i]=(a[i+1]-a[i]+k)%k;     for(int i=0;i<m-1;i++)        db[i]=(b[i+1]-b[i]+k)%k;        n--;        m--;        kmp();    }    return 0;}


阅读全文
0 0
原创粉丝点击