KMP-MUH and Cube Walls-CodeForces - 471D

KMP-MUH and Cube Walls-CodeForces - 471D

题意:

给 定 长 度 为 n 的 整 数 序 列 a 和 长 度 为 m 的 整 数 序 列 b , 其 中 b 序 列 可 以 将 所 有 数 同 时 增 加 或 减 少 h , 问 在 可 以 修 改 b 的 情 况 下 , 序 列 b 在 a 中 最 多 能 够 匹 配 成 功 几 次 。 给定长度为n的整数序列a和长度为m的整数序列b,其中b序列可以将所有数同时增加或减少h,\\问在可以修改b的情况下,序列b在a中最多能够匹配成功几次。 nambbhbba

输入输出:
在这里插入图片描述

如 样 例 : 将 序 列 b 同 时 增 加 1 得 到 : 4   5   5   4   3 , 与 序 列 a 第 二 个 位 置 起 的 子 串 成 功 匹 配 。 将 序 列 b 同 时 减 少 1 得 到 : 2   3   3   2   1 , 与 序 列 a 的 长 度 为 5 的 后 缀 成 功 匹 配 。 因 此 共 成 功 匹 配 两 次 。 如样例:将序列b同时增加1得到:4\ 5\ 5\ 4\ 3,与序列a第二个位置起的子串成功匹配。\\ \qquad \qquad 将序列b同时减少1得到:2 \ 3 \ 3 \ 2 \ 1,与序列a的长度为5的后缀成功匹配。\\因此共成功匹配两次。 b14 5 5 4 3ab12 3 3 2 1a5

题解:

序 列 匹 配 问 题 , 考 虑 K M P 算 法 。 序列匹配问题,考虑KMP算法。 KMP

事 实 上 , 无 论 序 列 b 同 时 增 加 或 减 少 多 少 , 相 邻 两 个 数 的 差 是 不 会 改 变 的 。 因 此 , 我 们 只 需 要 将 序 列 a 和 b 差 分 一 次 , 再 去 匹 配 它 们 的 差 分 数 组 即 可 。 事实上,无论序列b同时增加或减少多少,相邻两个数的差是不会改变的。\\因此,我们只需要将序列a和b差分一次,再去匹配它们的差分数组即可。 bab

注意:

差 分 数 组 的 长 度 比 原 数 组 的 长 度 小 1 。 差分数组的长度比原数组的长度小1。 1

代码:


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define ll long long
#define inf 0x7fffffff
using namespace std;
const int N=2e5+10;
int Next[N],n,m;
int a[N],b[N];
int da[N],db[N];
void get_next()
{
    for(int i=2,j=0;i<m;i++)
    {
        while(j&&db[i]!=db[j+1]) j=Next[j];
        if(db[i]==db[j+1]) j++;
        Next[i]=j;
    }
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++) scanf("%d",&b[i]);

    if(m==1) {cout<<n<<endl;return 0;}

    for(int i=1;i<n;i++) da[i]=a[i+1]-a[i];
    for(int i=1;i<m;i++) db[i]=b[i+1]-b[i];

    get_next();

    int cnt=0;
    for(int i=1,j=0;i<n;i++)
    {
        while(j&&da[i]!=db[j+1]) j=Next[j];
        if(da[i]==db[j+1]) j++;

        if(j==m-1)
        {
            cnt++;
            j=Next[j];
        }
    }

    printf("%d\n",cnt);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值