前言

题目链接:洛谷

上一题之后,模拟赛又放了一道 KMP 重定义相等的问题,但是寄了,故再记之。

题意简述

现在给出 \(1 \sim n\) 的排列 \(p\) 和序列 \(h_1, h_2, \cdots, h_m\)​​,请你求出哪些 \(h\) 的子串符合排列 \(p\)。串 \(a_i\) 符合一个排列被定义为其从小到大排序后得到 \(a_{p_i}\)。

题目分析

先想到定义 \(b_{p_i} = i\),那么一个串符合 \(p\),等价于其每个值的排名与 \(b_i\) 相等。

也是考虑,用相对信息来进行匹配。很容易想到,如果对于两个串,每个位置的前驱后继都相等,这两个串是符合上述“符合”的定义的。因为每个数都能够确定在排名中唯一的位置。

由于 KMP 匹配的过程是从左往右扫的过程,我们如果要记相对信息,只能记这个位置和之前位置的相对关系。这是对于 KMP 重定义匹配普遍的结论。这是为什么呢?

比如,之前我们有一个位置和后面的相对信息超出了当前匹配的范围,我们当做它不存在。但是,随着我们向右扫描的过程中,这个位置可能有被包含了进来,就有可能不符合要求。相反,如果我们记录左边的信息,如果超出范围,就不可能再被包含进来,所以不会出现以上情况。

那我们如何设计新的信息呢?我们假设之前匹配到的位置都暂时符合排名关系,那要新增一个值,让这个值也符合排名位置。这是一个类似于在一个有序的数列里面插入一个值,使得这个值插入的位置满足给出的信息。想到,对于 \(b\) 可以预处理出 \(L_i\) 和 \(R_i\) 分别表示 \(i\) 与在 \(1 \sim i - 1\) 中的前驱后继之差。这也和我们要插进去的位置相关。

所以,假设当前位置为 \(i\),\(i - 1\) 匹配到的位置为 \(j\),我们只需要判断 \(S[i - L[j + 1]] < S[i] < S[i + R[j + 1]]\) 就表示可以插到对应位置,满足要求。当然,如果 \(L[j + 1]\) 或 \(R[j + 1]\) 不存在则无需判断。

至于预处理 \(L\) 和 \(R\),由于 \(b\) 是排列,所以倒序枚举,链表查前驱后继并删去当前数即可。

时间复杂度为 \(\Theta(n + m)\)。

代码

略去了快读快写,是最优解

// #pragma GCC optimize(3)
// #pragma GCC optimize("Ofast", "inline", "-ffast-math")
// #pragma GCC target("avx", "sse2", "sse3", "sse4", "mmx")
#include <cstdio>
using namespace std; int n, m;
int xym[1000010], yzh[1000010];
int whr[1000010], fail[1000010];
int L[1000010], R[1000010];
int pre[1000010], nxt[1000010];
int ans[1000010], tot; inline bool check(int *yzh, int x, int y) {
return (!L[x] || yzh[y + L[x]] < yzh[y]) && (!R[x] || yzh[y + R[x]] > yzh[y]);
} signed main() {
fread(buf, 1, MAX, stdin), read(n), read(m);
for (int i = 1; i <= n; ++i) {
read(whr[i]), xym[whr[i]] = i;
pre[i] = i - 1, nxt[i] = i + 1;
}
for (int i = n; i; --i) {
if (pre[xym[i]] ) L[i] = whr[pre[xym[i]]] - i;
if (nxt[xym[i]] <= n) R[i] = whr[nxt[xym[i]]] - i;
pre[nxt[xym[i]]] = pre[xym[i]];
nxt[pre[xym[i]]] = nxt[xym[i]];
}
for (int i = 1, j = fail[0] = -1; i <= n; ++i) {
while (~j && !check(xym, j + 1, i)) j = fail[j];
fail[i] = ++j;
}
for (int i = 1; i <= m; ++i) read(yzh[i]);
for (int i = 1, j = 0; i <= m; ++i) {
while (~j && (j == n || !check(yzh, j + 1, i))) j = fail[j];
if (++j == n) ans[++tot] = i - n + 1;
}
write(tot), putchar('\n');
for (int i = 1; i <= tot; ++i) write(ans[i]), putchar(' ');
fwrite(obuf, 1, o - obuf, stdout);
return 0;
}

[CEOI2011] Matching 题解的更多相关文章

  1. 【LOJ#2507】[CEOI2011]Matching(KMP,树状数组)

    [LOJ#2507][CEOI2011]Matching(KMP,树状数组) 题面 LOJ 题解 发现要做的是排名串的匹配. 然后我们考虑把它转成这个位置之前有多少个数小于当前这个数,这样子只要每个位 ...

  2. [LeetCode] Wildcard Matching 题解

    6. Wildcard Matching 题目 Implement wildcard pattern matching with support for '?' and '*'. '?' Matche ...

  3. luoguP4696 [CEOI2011]Matching KMP+树状数组

    可以非常轻易的将题意转化为有多少子串满足排名相同 注意到$KMP$算法只会在当前字符串的某尾添加和删除字符 因此,如果添加和删除后面的字符对于前面的字符没有影响时,我们可以用$KMP$来模糊匹配 对于 ...

  4. LOJ2507 CEOI2011 Matching

    题目链接 参考了 神仙yyb的博客 现在发现kmp不仅能匹配字符串,还可以用于处理任意模式匹配中的状态,如这题中已经匹配的序列中的数的大小关系就是一种状态,使用kmp找到模式序列的每一个前缀的bord ...

  5. O - Matching 题解(状压dp)

    题目链接 题目大意 给你一个方形矩阵mp,边长为n(n<=21) 有n个男生和女生,如果\(mp[i][j]=1\) 代表第i个男生可以和第j个女生配对 问有多少种两两配对的方式,使得所有男生和 ...

  6. LeetCode题解-----Wildcard Matching

    题目描述: '?' Matches any single character. '*' Matches any sequence of characters (including the empty ...

  7. 《LeetBook》leetcode题解(10): Regular Expression Matching——DP解决正则匹配

    我现在在做一个叫<leetbook>的免费开源书项目,力求提供最易懂的中文思路,目前把解题思路都同步更新到gitbook上了,需要的同学可以去看看 书的地址:https://hk029.g ...

  8. LeetCode题解——Regular Expression Matching

    题目: 正则表达式的匹配,'.'能匹配任何一个字符,'*'之前必须有一个字符,两个结合起来表示之前那个字符出现0到无穷次. 解法: 一定要注意'*'必须结合前面的字符一起使用. 代码: class S ...

  9. [LeetCode]题解(python):010-Regular Expression Matching

    题目来源: https://leetcode.com/problems/regular-expression-matching/ 题意分析: 这道题目定义了两个正则表达式规则.’.’代表任意字符,’* ...

  10. [LeetCode]题解(python):044-Wildcard Matching

    题目来源: https://leetcode.com/problems/wildcard-matching/ 题意分析: 定义两个新字符规则,'?'代表任意一个字符,’*‘代表任意长度的任意字符.输入 ...

随机推荐

  1. 配置h5py、netCDF4库的方法:Anaconda环境

      本文介绍基于Anaconda环境,下载并安装Python中h5py与netCDF4这两个模块的方法.   在Python语言中,h5py与netCDF4这两个模块是与遥感图像处理.地学分析等GIS ...

  2. 2-SET详解

    前置知识 SET问题的标准定义:在计算机科学中,布尔可满足性问题(有时称为命题可满足性问题,缩写为SATISFIABILITY或SAT)是确定是否存在满足给定布尔公式的解释的问题.(全是废话) 说人话 ...

  3. Nuxt3 的生命周期和钩子函数(七)

    title: Nuxt3 的生命周期和钩子函数(七) date: 2024/6/30 updated: 2024/6/30 author: cmdragon excerpt: 摘要:文章阐述了Nuxt ...

  4. 实测952Mbps!四路千兆网PCIe拓展方案,国产工业级!

    测试环境说明 运行系统:Debian-11.8 评估板:TL3588-EVM(RK3588J) 模块:PCIe扩展2/4路千兆网口模块 方案:无锡沐创N500L-AM2C-DD.N500L-AM4C- ...

  5. 【Hive报错】在hue上执行自定义的hive函数报错 Error while compiling statement:FAILED:SemanticException [Error 10011]: Invalid function default.sqlServerdes

    在 Hive客户端中使用自定义创建UDF函数时,报"ERROR 10011","invalid function"的异常: 在Hive上自定义创建了一个函数,在 ...

  6. 记一次debian无法启动的解决经历

    前言 有几台debian物理机突然无法开机了,断电重启后,一直卡在下面这个界面 参考了博客[linux]解决系统卡在ubuntu loading initial ramdisk 发现无法修复 在rec ...

  7. K210开发板学习笔记-点亮LED灯

    1. 介绍 和 51 单片机非常像,实验的2个LED灯都是一头接了 +3.3v 电源,控制 LED灯亮的话需要 K210芯片 对应的管脚提供一个低电平. 管脚: 低电平-LED亮 高电平-LED灭 G ...

  8. Aspose Excel 单元格合并后边框显示不全

    /// <summary> /// 解决合并后的单元格没有边框,设置合并单元格格式,让合并过的单元格中每一个单元格上都添加上加边框的样式 /// </summary> /// ...

  9. 自学Java第二周

    本周学习 一.Java能干些什么? 1.共三个版本:Java SE.Java EE.Java ME Java SE:Java语言的(标准版),用于桌面应用开发,是其他两个版本的基础. Java ME: ...

  10. influxdb得导出与导入

    转载请注明出处: 1.备份元数据 基本语法: influxd backup <path-to-backup> 备份元数据,没有任何其他参数,备份将只转移当前状态的系统元数据到path-to ...