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)$。

相關文章
相關標籤/搜索