VI. 字符串

前言

字符串的知识点在OI中相对比较成体系,而且内容并不太多。
字符串的重点内容在于匹配,即两个串的完全相等关系。除此之外还涉及字典序、自动机、周期等等。
相等这一关系虽然平凡,但是在字符串算法中,可以看到它的性质被深入的挖掘,得到不平凡的一系列结果。

基本知识

字符串哈希

2022年了,希望大家使用正统的多项式哈希+双哈希,不要不识好歹使用自然溢出+base=4之类的诡异操作
哈希处理字符串匹配问题的思路常常与其他字符串数据结构完全不同。
配合数据结构,它能直接的支持对所维护字符串的单点修改、拼接乃至区间翻转之类的动态字符串操作。而这是其他字符串数据结构很难做到的。

KMP & AC自动机

二者最重要的作用就是求匹配。
多串匹配问题中,AC自动机能起到非常大的作用。
二者的原始版本复杂度分析都是均摊的。不过,建成“Trie图”的自动机形式+可持久化线段树可以避免均摊的影响。
KMP能求出每个前缀的border,配合border理论会有一些作用。

Trie树

Trie树是字符串数据结构!不要被异或蒙蔽了双眼!
它能处理一些LCP、字典序问题这种前缀性质的问题。而且可以把问题变得直观。

exkmp(Z函数)

听说exkmp和KMP是等价的?
能求一个串和它的前缀的LCP,功能被SA偏序,但是复杂程度和常数远胜。

manacher & PAM

处理回文串的利器,但是形式略有不同。

SA & SAM & 后缀树

后缀三兄弟
表示一个串的子串结构的重要方法。
求LCP和endpos的主要手段。但是有时在匹配问题上不如AC自动机。
有时也利用它们处理字典序,或是在字典序上二分。

重要结论

Border & 周期

  1. Border和周期一一对应。
  2. 周期引理:p,q 是周期且 p+qgcd(p,q)ngcd(p,q) 是周期。
    简单推论:小于一半的周期都是最小正周期的倍数
  3. 重要推论:一个串的Border构成 log 个值域不交的等差数列。

Lyndon & Runs

  1. Lyndon串的两种定义:字典序在所有循环移位中严格最小;字典序在所有后缀中最小。
  2. Runs Theorem:一个串的Runs个数不超过 n,Runs的指数之和不超过 3n

处理方法

一般方法

子串是后缀的前缀,遇到问题时首先考虑是否能转化成前缀/后缀问题。
如果转化成“前缀和后缀相等”,考虑AC自动机fail树的结构(在单串情况下退化成Border树)。
常用的伎俩还有将相等关系转化为两个后缀的LCP不小于某数。
至于字典序相关的问题,Trie树/后缀树才是最为直观的表示方法。

“关键点”方法

主要用于求平方串/求Runs这种具有至少2倍周期的结构。
例子:[NOI2016]优秀的拆分。

数据结构方法

在parent树/fail树上将问题直接转化成树上数据结构问题。
通常配合的树上算法有线段树合并、dsu on tree等等。还要学会如何优雅的线段树上二分

自动机方法 1

直接利用自动机的结构可以解决一些非常长的字符串问题。
非常长以至于不能扫描一遍的字符串当然不可能是任意的,往往有一定的规律,如:构成具有周期性/自相似性;可以由少量有规律的串拼接重复而成。

自动机方法 2

处理“一个母串的子串……”类的问题十分常见。
考虑长字符串输入自动机时的结果/询问串输入母串自动机的结果,可以利用起它的特殊性。
此外,逐字符将询问串输入自动机的过程可以求出询问串每个前缀的一些信息,而不止于整个串。
例子:[NOI2018]你的名字

bitset方法

最为离谱的做法,适用于其他字符串数据结构完全做不了的情况。
常用的方法是用字符出现位置集合的位移取交来代替“相等”“匹配”。
和字符集大小密切相关,甚至可以通过扩大字符集大小来平衡常数
也可以处理一些动态字符串。

动态字符串问题

如果是单端插入,可能可以利用字符串算法的性质动态维护。(KMP、SAM、PAM、后缀树都是逐字符加入的)。
这可以解决一些离线询问问题。但更多的时候是题目强制要求动态维护。
当变化的形式更为复杂时,哈希往往才是最好的选择。

其他知识

因为好像不那么重要就往下移了……
包括最小表示法的专用算法、Duval算法、广义SAM、(对称)压缩SAM、后缀平衡树等难得一见的东西
组合字符串相关的深入学习参考金策的字符串课件,这个好像在江湖上流传甚广。

posted @   秋叶冬雪  阅读(238)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示