字符串 - 基础字符串

周期与边界理论

字符集:\(\Sigma\)

字符串:\(\cup_{k\ge 0}\Sigma^k\) 的一个元素。其中集合乘法是笛卡尔积。记 \(n=|s|\)

子串:记作 \(s_{l,r}\)

周期 (Period):\(p\)\(s\) 的周期,当且仅当 \(s\)\(p^{+\infty}\) 的前缀。若 \(|p|\mid |s|\)\(p\)\(s\) 的整周期(不同于正周期)。

周期 (Period)

弱周期引理 (Weak Periodicity Lemma)

\(p,q\) 都是 \(s\) 的周期,且 \(p+q\le n\),那么有 \(\gcd(p,q)\) 也是 \(s\) 的周期。

证明:归纳。假设 \(p<q\),对于 \(1\le i\le n\),有 \(i>p\)\(i<n-q+1\) 其一成立(两者同时成立取后者)。前者可以推出 \(s_i=s_{i-p+q}\),后者有 \(s_i=s_{i+q-p}\),即 \(q-p\) 也是 \(s\) 的一个周期,归纳得证。

强周期引理 (Periodicity Lemma)

\(p,q\) 都是 \(s\) 的周期,且 \(p+q\le n+\gcd(p,q)\),那么有 \(\gcd(p,q)\) 也是 \(s\) 的周期。

为什么界是紧的?

\(s=\texttt{ABACABA},p=4,q=6\),引理不成立。

证明

假设 \(p>q\)。首先 \(p-q\)\(s\) 长度为 \(n-q\) 的前缀(后缀)周期,因为对于 \(i<i+p-q\le n-q\),有 \(s_{i}=s_{i+p-q}\)(后缀同理)。

【重点】归纳。由于 \(p+q\le n+\gcd(p,q)\)\(p+q-q\le n-q+\gcd(p-q,q)\),故 \(\gcd(p,q)\)\(s\) 长度为 \(n-q\) 的前缀(后缀)周期。

于是 \(\gcd(p,q)\)\(s\) 长度为 \(n-q\) 的后缀周期,而 \(s\) 长度为 \(q\) 的前缀也有 \(\gcd(p,q)\) 作为周期,综上所述 \(s\)\(\gcd(p,q)\) 作为周期。

边界 (Border)

Border 与 Period

长度为 \(b\) Border 对应着长度为 \(n-b\) 的 Period。

证明:任取长度为 \(b\) 的 Border,则对于 \(1\le i\le b\)\(s_i=s_{n-b+i}\),即存在一个长度为 \(n-b\) 的 Period。显然构成满射,故构成双射。

Border 构成等差数列

引理 1

\(s\) 的所有长度大于等于一半的 Border(包括整个串) 构成一段等差数列。

考虑 \(s\) 的最小周期 \(p\),任取 \(p<q\le \dfrac{n}{2}\),根据弱周期引理 \(\gcd(p,q)=p\) 也是 \(s\) 的周期,故 \(p\mid q\),所有 \(q\) 构成等差数列。

引理 2

定义 \(s-t\) 的 Border 为 \(s\) 长度为 \(b\) 的前缀等于 \(t\) 长度为 \(b\) 的后缀的所有 \(b\),则 \(s,t\) 的所有长度大于等于一半的 Border 构成一段等差数列。

取出最大 Border,其余显然略去。

定理

\(s\) 的所有 Border(包括整个串) 构成至多 \(\log_2 n\) 等差数列。

构造 1:
取出 \(s-s\) \(\ge\) 一半的 Border 构造等差数列,剩下长度 \(<\dfrac{n}{2}\) 的 Border,递归 \(s\) 长度为 \(\dfrac{n}{2}\) 的前缀 \(-\) \(s\) 长度为 \(\dfrac{n}{2}\) 的后缀递归构造。

构造 2:
\(2\) 为基数倍增对值域分块,同一块内显然构成等差数列。

KMP 算法

线性求 \(t\)\(s\) 中的出现位置。

首先求出 \(t\) 的最长 Border,然后记录 \(t\) 的结尾匹配 \(s_i\),其他字符向前匹配的最长长度。

应用

LOJ10035 「一本通 2.1 练习 1」Power Strings

\(s\) 的最小整周期。

事实上,由 Border 理论可知,\(s\) 的最小整周期只有可能是 \(n-\) 最小 Border。

[NOI2014] 动物园

\(s\) 每个前缀计算出它有多少个 Border 长度都不超过该前缀长度的一半。

\(\Theta(n+m)\) 模拟 KMP 的过程,维护最长不超过该前缀长度的一半的 Border。

Shift-And 算法

\(\Theta(\dfrac{nm}{w})\) 地求 \(t\)\(s\) 中的出现位置。

\(f_i\) 表示 \(s\) 长度为 \(i\) 的前缀与 \(t\) 是否匹配(从后向前),将 \(t\) 增加一位时,\(f'_i\) 可以 bitset 求出。

P4465 [国家集训队] JZPSTR

维护字符串,支持:插入、删除、查询指定字符串在指定区间出现次数。

ExKMP

线性求 \(t\) 的每个后缀与 \(s\) 的最长公共前缀。

首先类似 Manacher 求出 \(s\) 的 Z 函数,Z 函数定义为最大的 满足 \(s_{1,k}=s_{i,i+k−1}\)\(k\)(Border 是满足 \(s_{1,k}=s_{i-k+1,i}\)\(k\))。然后就可以类似地求答案了。

BZOJ4974 字符串大师

给定 Border,求 Z 函数。

模拟 KMP 的过程。

Aho-Corasick 自动机

\(t_1,t_2,t_3\ldots\)\(s\) 中的出现位置。

AC 自动机由 Trie 树和 Fail 树组成,其中一个结点在 Fail 树上的父亲是存在的最长后缀(可以 \(\Theta(\sum |t_i|)\) 或者 \(\Theta(n|\Sigma|)\) 或者可持久化做到 \(\Theta(n\log|\Sigma|)\),其中 \(n\) 是 Trie 上的结点数)。

每个点在 Trie 树上的祖先是它的前缀,在 Fail 树上的祖先是它的后缀。

\(t_i\) 构建 AC 自动机,对 \(s\) 类似 KMP 地进行查找即可(或者直接把 \(s\) 插入)。

P2414 [NOI2011] 阿狸的打字机

\(n\) 个串,\(q\) 次询问一个串在另一个串中出现次数。

也就是询问 Trie 树上 \(x\) 的祖先中有多少个在 Fail 树上 \(y\) 的子树内。二维数点。

CF710F String Set Queries

维护字符串集合,支持 加、删、查询集合中的所有字符串在给出的模板串中出现次数和。强制在线。

强制在线可以使用二进制分组。

P8203 [传智杯 #4 决赛] DDOSvoid 的馈赠

给定 \(n\) 个模式串 \(s\)\(m\) 个文本串 \(t\)\(q\) 次询问求有多少模式串既是 \(t_x\) 的子串,也是 \(t_y\) 的子串?

根号分治。

UOJ772 企鹅游戏

给定若干模式串 \(t_i\) 和若干文本串 \(s_i\)。对每个文本串,求每个模式串出现次数。

我们知道,在只有一个文本串的情况下,所有模式串(所有模式串互不相同)出现次数之和\(\Theta(|s|\sqrt{\sum |t_i|})\)

可以证明,当模式串互不相同时,每个文本串包含的 本质不同模式串个数(注意不是出现次数)之和是 \(\Theta(L^{4/3})\)

AC 自动机维护文本串子串的匹配信息

给定文本串 \(s\) 若干模式串 \(t_1,t_2,\ldots,t_n\)\(q\) 次查询 \(t_1,t_2,\ldots,t_n\)\(s_{l,r}\) 中的出现次数和。

不妨将 \(s\) 和所有 \(t\) 插入 AC 自动机。

枚举 \(r\),记 \(f_l\) 表示 \(s_{l,r}\) 的匹配信息(出现次数和)。

考虑 \(r+1\to r\) 时,记 \(u\) 为匹配结点,对于 Fail 树上 \(u\) 的所有祖先 \(v\)\(v\) 是完整的模式串),会对 \(f_{1},f_2,\ldots,f_{|u|-|v|+1}\)\(1\)。直接暴跳是 \(n\sqrt{n}\) 的复杂度。

考虑 \(u\) 的 Border,记为 \(w\)\(f_{|u|-|w|+1},f_{|u|-|w|+2},\ldots,f_r\) 都是已经计算过的,可以直接继承 \(r\)\(|w|\) 处的 \(f\) 值。且我们有结论:随着 \(r\) 的移动,\(|u|-|w|+1\) 单调不减,故对于 \(f_1,f_2,\ldots,f_{|u|-|w|}\) 也是容易维护的。一个简单的想法是使用可持久化平衡树。

由于 \(f_1,f_2,\ldots,f_{|u|-|w|}\) 容易线性维护,假设 \(r-1\) 的 Border 为 \(w'\),我们需要快速求出 \(f_{|u|-|w'|},f_{|u|-|w'|+1},\ldots,f_{|u|-|w|}\)。对反串构建自动机。这样我们如果能求出 \(f_{|u|-|w|}\) 匹配到的状态和 \(f\) 值,就可以线性在反串自动机上继续匹配求出所有 \(f\) 值。

所有正串 AC 自动机状态(每个前缀)求出反串匹配状态一定是整个串在 AC 自动机 Fail 树的祖先,找到最深的长度不超过原状态长度的祖先即可,可以双指针线性求解。

综上,整个问题得到线性求解。

最小表示

求字典序最小循环移位。

Manacher

求最长回文子串。

求出所有本质不同回文子串:只有当 \(r\) 更新时所得的字符串是和之前本质不同的。

回文自动机

回文自动机的每个状态对应一个回文子串。由转移边和 Fail 树构成。经过一条转移边在前后添加一个字符,一个状态在 Fail 树上的父亲是其最长回文 Border。

回文自动机的转移边构成了两棵 Trie 树,分别对应长度为奇数的回文子串和长度为偶数的回文子串。

增量法构建,可以强制在线,支持双端插入。

P4287 [SHOI2011] 双倍回文

给定字符串,计算它的最长双倍回文子串的长度。

维护长度小于等于 \(|s|/2\) 的 Border 所在节点。也可以 Manacher 求。

QOJ5440 P-P-Palindrome

给你 \(n\) 个字符串,求出有多少字符串本质不同有序对 \((P,Q)\),满足:\(P\), \(Q\), \(P+Q\) 都是回文串且 \(P,Q\)\(n\) 个字符串中至少一个的子串。

对于回文串 \(P,Q\) 有结论:\(P+Q\) 回文当且仅当 \(P,Q\) 最小整周期完全相同。

充分性显然,证明一下必要性:

假设 \(P+Q\) 回文,那么 \(P+Q,P,Q\) 最小整周期都一定为 \(\gcd(|P|,|Q|)\) 的因数。(可以由弱周期引理得到)
因此,如果 \(P,Q\) 最小循环节不相等,那么 \(P,Q\) 的前 \(\gcd(|P|,|Q|)\) 个字符肯定也不相同,因此不合法。

因此,我们对每个本质不同的回文串求出最小循环节的 Hash,答案即为有多少对相同的 Hash 值。

PAM 图

类似 Trie 图,我们也可以定义 PAM 图使得这些操作的时间复杂度不用均摊。使用类似记忆化的方法,对每个状态,预处理出它后面添加字符 跳到的祖先,这样就能 \(\Theta(n\Sigma)\) 建出 PAM 图。

NowCoder33189F Palindromic Tree

给定一棵树,每条边上有一个字符。\(q\) 次查询两点路径上的所有边拼起来形成的字符串的本质不同回文子串个数。

树 分 块。使用 PAM 图保证复杂度。

后缀自动机

Endpos 集合与上下文

对于 \(s\) 的一个子串 \(t\),记 \(\operatorname{endpos}(t)=\{r\mid s_{l,r} = t\}\)。类似地,记 \(\operatorname{beginpos}(t) = \{l\mid s_{l,r} = t\}\)

\(t\) 的上文是最长的 \(t'\) 使得 \(\operatorname{endpos}(t)=\operatorname{endpos}(t')\)
\(t\) 的上文是最长的 \(t'\) 使得 \(\operatorname{beginpos}(t)=\operatorname{beginpos}(t')\)

\(t\) 的上下文是 \(t\) 的上文的下文。可以证明 \(t\) 的上文的下文等于 \(t\) 的下文的上文。

后缀自动机

后缀自动机(简称 SAM)是可以接受一个串的所有后缀的自动机。

后缀自动机由转移边和 Fail 树构成,每个状态对应一组 \(\operatorname{endpos}\) 相同的子串,经过一条转移边对一个串的影响是在其末尾添加字符,一个状态在 Fail 树的父亲是 \(\operatorname{endpos}\) 不同于它的后缀中最长的一个。

构建

每个状态维护 \(\operatorname{len}\),表示其中最长的一个串的长度。

参考资料

posted @ 2023-11-01 17:36  Network_Error  阅读(94)  评论(0)    收藏  举报