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