Gym 100431EWord Cover 题解:KMP上跑dp
題意:
?
給你一個串,問你他的每個前綴的最小重復單元,其中單元是可以重疊的,最后按順序輸出即可。比如樣例中abaabaa的最小重復單元為abaa,所以相應輸出為4。
樣例:?
input :?abaabaababa
output:1 2 3 4 5 3 4 5 3 10 3
?
?
kmp過程就不用多說了,現在我們利用next數組的性質來對問題進行求解。
我們首先用一個ans[maxn]數組來記錄最后的答案,且我們的字符串下標從0開始,顯然,我們ans[i]的最大值為i+1,我們因此也用此值對其進行初始化。
現在我們考慮什么情況下ans[i]可以得到更小的,更小他能達到多小。
其實這個顯然可以知道第i位的ans值只能從ans[next[i]]那里獲得,這個就可以根據next數組的性質想一想就明白了,若存在更短的,到i的后面的這段就不成立了。
然后我們考慮i和next[i]位置的兩種情況:
第一種情況:i - next[i] ≤ next[i]
此時顯然就可以利用ans[next[i]]進行更新了,如果可以形成前面這段,那么一定可以形成后面那段。
第二種情況:i - next[i] > next[i]
這種情況就是此題的難點所在了,乍看之下似乎這種情況下只能放棄用ans[next[i]]來更新ans[i]了,其實不然!!!
樣例就給我們了很好的反例,因為樣例最后一位的答案是3!
我們用dp[k]來記錄最后ans是k的最大的下標,我們假設cnt = ans[next[i]],即在next[i]處的答案,然后如圖:
一個比較顯而易見的是cnt ≤ next[i]是肯定成立的,而此種假設下我們假設i - next[i] ≤ next[i],現在決定最終成敗的就只剩下dp[cnt]的具體位置了!!!
我們證明 i - dp[cnt] ≤ cnt 時的情況必然可以用cnt來更新ans[i]。
此時狀況完全如上圖所示,此時在dp[cnt]前已經得知必可由長度為cnt的串來產生,而這cnt長得串同時也肯定是從0到next[i]中長度為cnt的后綴。那么根據next數組的性質,這段串與i-cnt ~ i這段是相同的。我們又假設了?i - cnt ≤ dp[cnt] ,因此我們的i-cnt ~ i這段必然可由與形成dp[cnt]長度相同的串來產生,同時這也是其所有可能的最小答案。
最后當next[i] = -1 的時候就沒什么說的了,顯然上面說的這些都沒用了,直接就賦值給 ans[i] = i + 1,再更新一下 dp[ans[i]] = i 就可以了。
在此表達對此神作法的膜拜之情!
本弱渣的代碼如下:
?
轉載于:https://www.cnblogs.com/ScratchingBear/p/5345825.html
總結
以上是生活随笔為你收集整理的Gym 100431EWord Cover 题解:KMP上跑dp的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tcp服务器客户端状态图
- 下一篇: 一个大浪Java罢工(一个)安装JDK和