2011年就能出出這樣充滿科技感+腦力的題,佩服POI Orz
簡記一下做法和證明,順便復習 border 的一些性質。
注意真的是簡記,有很多東西需要自己好好推一下……
約定:字符串 \(s\) 的下標從 \(0\) 開始,\(s_{i,j}\) 表示 \(s\) 的第 \(i\) 到第 \(j\) 個字符構成的子串。
串 \(s\) 有長度為 \(l\) 的周期等價於其有長度為 \(|s|-l\) 的 border。
設函數 \(solve(s)\) 表示字典序最小的、border 集合與 \(s\) 的 border 集合相同的 \(01\) 字符串。分為以下情況:
- 如果 \(s\) 中所有字符相同,返回 \(|s|\) 個 \(0\) 構成的字符串;
- 如果 \(s\) 周期集合為空,返回 \(|s| - 1\) 個 \(0\) 接上 \(1\) 個 \(1\) 構成的字符串;
- 如果 \(s\) 最短的周期長度 \(len\) 滿足 \(2len \leq |s|\),設 \(t = s_{1,len}\),則 \(s\) 可表示為 \(ttt...tt'\) 的形式,其中 \(t'\) 是 \(t\) 的一個前綴,可為空。
- 如果 \(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)\) 的流程:
- 如果 \(s\) 中所有字符相同,返回 \(|s|\) 個 \(0\) 構成的字符串;
- 如果 \(s\) 周期集合為空,返回 \(|s| - 1\) 個 \(0\) 接上 \(1\) 個 \(1\) 構成的字符串;
- 如果 \(s\) 最短的周期長度 \(len\) 滿足 \(2len \leq |s|\),將 \(s\) 表示為 \(ttt...tt'\) 的形式,其中 \(t'\) 是 \(t\) 的一個前綴,可為空,設 \(qq' = solve(tt')\),則返回 \(q^{\lfloor \frac{|s|}{len} \rfloor}q'\);
- 如果 \(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)\)。
