POI2011 Periodicity


2011年就能出出这样充满科技感+脑力的题,佩服POI Orz

简记一下做法和证明,顺便复习 border 的一些性质。

注意真的是简记,有很多东西需要自己好好推一下……


约定:字符串 \(s\) 的下标从 \(0\) 开始,\(s_{i,j}\) 表示 \(s\) 的第 \(i\) 到第 \(j\) 个字符构成的子串。

\(s\) 有长度为 \(l\) 的周期等价于其有长度为 \(|s|-l\) 的 border。


设函数 \(solve(s)\) 表示字典序最小的、border 集合与 \(s\) 的 border 集合相同的 \(01\) 字符串。分为以下情况:

  1. 如果 \(s\) 中所有字符相同,返回 \(|s|\)\(0\) 构成的字符串;
  2. 如果 \(s\) 周期集合为空,返回 \(|s| - 1\)\(0\) 接上 \(1\)\(1\) 构成的字符串;
  3. 如果 \(s\) 最短的周期长度 \(len\) 满足 \(2len \leq |s|\),设 \(t = s_{1,len}\),则 \(s\) 可表示为 \(ttt...tt'\) 的形式,其中 \(t'\)\(t\) 的一个前缀,可为空。
  4. 如果 \(s\) 最短的周期长度 \(len\) 满足 \(2len > |s|\),设 border 为 \(t\),那么 \(s\) 就可以表示为 \(tat\) 的形式,其中 \(a\) 是一个任意字符串,不能为空。

1 和 2 情况的构造是显然的。


对于 3 情况,递归进入 \(tt'\) 求解。设 \(qq' = solve(tt')\),那么就把 \(q\) 重复若干次拼上 \(qq'\),即可得到答案。

在证明正确性前先来复习有关周期和 border 的几个 OI 界众所周知的简单定理。

  • Weak Periodicity Lemma:对于一个字符串 \(s\),若其有长度为 \(p\) 和长度为 \(q\) 的周期,且 \(p+q \leq |s|\),则 \(s\) 有长度为 \(\gcd(p,q)\) 的周期。

Proof. 设 \(p < q\),令 \(d = q - p\)。因为 \(p + q \leq |s|\),所以 \(\forall i \in [0,|s|-1] , i - p \geq 0\)\(i+q < |s|\) 至少有一个成立,故可以先向后跳 \(q\) 再向前跳 \(p\),或者先向前跳 \(p\) 再向后跳 \(q\),可得 \(s_{i+d} = s_i\)。那么 \(q-p\) 也是 \(s\) 的周期。根据辗转相除法,\(\gcd(p,q)\) 也是 \(s\) 的一个周期。QED

  • 一个推论:设 \(s\) 最短周期长度为 \(l\),且 \(2l \leq |s|\),则 \(s\) 的 border 集合中 \(\geq l + (|s| \bmod l)\) 的元素一定构成集合 \(\{pl + (|s| \bmod l) | p \in Z^+ , pl + (|s| \bmod l) \leq |s|\}\)

Proof. 首先这些元素一定会包含在 border 集合内。考虑使用反证法证明不存在其他的元素。

设有不满足该形式的 border 长度 \(l'\),不妨设 \(l' = xl+(|s| \bmod l)+y(y \in [1,l-1])\)。那么在 \(s\) 的长度为 \((x+1)l + (|s| \bmod l)\) 的前缀中,\(l'\) 是它的一个 border,即 \(l-y\) 是这个前缀的周期,而 \(l\) 也是其周期,且因为 \(x \geq 1\)\((x+1)l + (|s| \bmod l) \geq 2l-y\),根据 Periodicity Lemma\(\gcd(l,l-y)\) 是这个前缀的周期,同时 \(\gcd(l,l-y) \mid l\) 所以 \(\gcd(l,l-y)\) 是原串的一个周期,与 \(l\)\(s\) 的最短周期长度不符。QED


根据推论我们可以知道如果 \(q\) 串不是满周期串(即可划分为若干个部分满足各个部分的字符串完全相同),那么 \(\geq |qq'|\) 的所有 border 都可以正确构造,而构造 \(qq'\) 的时候将 \(< |qq'|\) 的所有 border 都已经正确构造了,所以这样就是对的。

证明 \(q\) 不是满周期串是简单的:如果 \(q\) 是满周期串,不妨设 \(q = p^c\),其中 \(p\) 是一个字符串。那么 \(|qq'|-|p|\)\(qq'\) 最长的 border。而如果在原串中有这样的一个 border 且 \(q\) 是周期,那么可以立即导出 \(p\) 是周期,那么 \(q\) 就不是最小周期。


先说句闲话:情况 4 中所有利用 border 表示利用 border 导出的相等关系。充分利用相等关系是证明一些结论的关键。

对于 4 情况,先递归进入 \(s_{1,len}\) 求解。设 \(t = solve(s_{1,len})\),那么我们需要确定一个字典序最小的字符串 \(a\) 满足 \(s=tat\) 的最长 border 为 \(t\)

首先我们肯定希望 \(a\) 是全 \(0\) 的字符串。但是只有这一种选择显然不能覆盖所有的情况,比如 \(t = 0000\) 时这样会使得最长 border 变大导致构造不合法。考虑在什么情况下以全 \(0\) 串作为字符串 \(a\) 会导致不合法。不妨讨论更长的 border 中最短的长度 \(l\)

  • \(l \leq |t| + |a|\)\(t\) 串在前面加若干个 \(0\) 等于在后面加若干个 \(0\),可导出 \(t\) 是全 \(0\) 串。这种情况下可以选择若干个 \(0\) 后面加上一个 \(1\) 形成的字符串,这样就是最优。
  • \(l > |t| + |a|\),利用 border 和 \(s\) 串首尾均是 \(t\) 串可以得到若干相等关系,进而得到 \(t_{1,l-|t|-|a|}+a\)\(t\) 的一个周期,可表示为 \(bab...bab\) 形式,其中 \(b\) 是一个非全 \(0\) 字符串。此时设 \(a'\) 为将 \(a\) 最后的 \(0\) 换成 \(1\) 得到的字符串,考虑把中间的 \(a\) 换成 \(a'\) 之后得到的字符串 \(s'\)。设它存在长度 \(>|t|\) 的 border ,不妨设长度为 \(l\)
    • \(l < |t| + |a'|\),在 \(t\) 前面加上 \(000...001\) 和在后面加上 \(000...000\) 得到相同的字符串,可以导出 \(t\) 中一个字符需要既等于 \(0\) 又等于 \(1\),不可能;
    • \(l \geq |t| + |a|\)。利用 border 和 \(t\) 串的循环串性质可以得到 \(bab\) 串中的某一段子串需要同时匹配 \(a'\)\(a\),这是不能做到的。

至此可以得出将 \(a\) 的最后一个 \(0\) 换成 \(1\) 得到的串一定是合法的,而它显然是最优的。


梳理一下 \(solve(s)\) 的流程:

  1. 如果 \(s\) 中所有字符相同,返回 \(|s|\)\(0\) 构成的字符串;
  2. 如果 \(s\) 周期集合为空,返回 \(|s| - 1\)\(0\) 接上 \(1\)\(1\) 构成的字符串;
  3. 如果 \(s\) 最短的周期长度 \(len\) 满足 \(2len \leq |s|\),将 \(s\) 表示为 \(ttt...tt'\) 的形式,其中 \(t'\)\(t\) 的一个前缀,可为空,设 \(qq' = solve(tt')\),则返回 \(q^{\lfloor \frac{|s|}{len} \rfloor}q'\)
  4. 如果 \(s\) 最短的周期长度 \(len\) 满足 \(2len > |s|\),设 \(t = s_{1,len} , q = solve(t)\)。检验 \(t+000...000+t\) 的最长 border 是否为 \(len\),若否将最后一个 \(0\) 替换为 \(1\),然后将该串返回。

至于如何 check 全 \(0\) 串是否合法,暴力 KMP 一遍即可。由 \(T(n) = T(\frac{n}{2}) + O(n)\) 可得复杂度为 \(O(n)\)

相关