POI2011 Periodicity

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

简记一下作法和证实,顺便复习 border 的一些性质。code

注意真的是简记,有不少东西须要本身好好推一下……递归


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

串 $s$ 有长度为 $l$ 的周期等价于其有长度为 $|s|-l$ 的 border。字符串


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

  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 状况的构造是显然的。io


对于 3 状况,递归进入 $tt'$ 求解。设 $qq' = solve(tt')$,那么就把 $q$ 重复若干次拼上 $qq'$,便可获得答案。循环

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

  • 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$ 的一个周期。QEDqq

  • 一个推论:设 $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)$。

相关文章
相关标签/搜索