字符串

简单写一写,以防后面忘了。

manacher

处理回文串有关的问题。具体地,对于一个字符串,manacher 可以线性地求出以其中的每个下标为中心的最长回文串的长度。

考虑如何做这个事情。首先长度为偶数的回文串因为没有中心所以难以处理,故考虑在字符串中任意相邻的位置间插入一个标记字符,同时在字符串的边界插入两个不同的标记字符。

接下来,设 \(w_i\) 表示以 \(i\) 为中心的最长回文串长度。考虑从左往右扫描求 \(w_i\) 的过程。

我们记 \(r\)\(\max\limits_{j = 1}^{i - 1} w_j\)\(p\) 为满足 \(w_p = r\) 的一个下标。接下来考虑 \(i\)\(r\) 的大小关系。若 \(i \le r\),则意味着以 \(p\) 为中心的回文串覆盖了 \(i\)。此时考察以 \(p\) 为中心的 \(i\) 的对称点 \(i'\),我们必定有 \(w_i \ge \min\{w_{i'}, r - i + 1\}\)。因此直接继承这个值,并在此基础上暴力扩展 \(w_i\) 并更新 \(r\)\(p\)

该做法正确性显然。复杂度上,若 \(i\) 不会更新 \(r\),则继承前面值后的运算次数必定为 \(O(1)\)。而对于 \(i\) 会更新 \(r\) 的情况,\(w\) 的总扩展次数必定为 \(O(n)\)。故总复杂度为 \(O(n)\),证毕。

模板代码:https://www.luogu.com.cn/record/234713996

KMP

线性解决两个字符串匹配的问题。

我们称在另一个字符串中匹配的字符串为模式串,被匹配的为文本串。

考虑对于模式串,预处理数组 \(\text{nxt}\)\(\text{nxt}_i\) 表示最大的满足 \(s_{[1, \text{nxt}_i]}\)\(s_{[1, i]}\) 后缀的值。显然对于 \(i\),我们可以从 \(\text{nxt}_{i - 1}\) 开始暴力跳去找 \(\text{nxt}_i\)。对于在文本串中匹配模式串的过程,也可以做类似的事情。

该做法的正确性可通过归纳证明得出。对于复杂度,考虑 \(\text{nxt}\) 数组最多只会向后拓展 \(n\) 次,而向前跳的次数必定不大于向后拓展的次数,故复杂度为 \(O(n + m)\),证毕。

posted @ 2025-09-08 11:36  zyb_txdy  阅读(6)  评论(0)    收藏  举报