Competitive Programming Note
本文已停止更新,新版請至 WiwiHo 的競程筆記
給一個字串 ,求 中最長的為迴文的子字串長度。
為了方便,接下來的索引值都是從 0 開始,也就是說, 的第一個字元是 。
首先,先求出以每個字元為中心點的最長迴文長度,但偶數長度的迴文沒有中心點,所以這邊做一個操作:在每個字元中間和 兩端加上一個 中沒有的字元 ,結果會是:。
這個加工過的字串為 ,長度是 ,可以用一個簡單的方式來得到 :
接下來的程式碼會用 為 .
作為範例。
接下來,我們用 來表示以 為中心點的最長迴文半徑(含中心點)。再來的重點是要如何快速求出 ,先從 的左邊讀到右邊,並且一邊計算 為何。
令 為目前為止,我們找到的迴文子字串的最右邊的結尾,也就是:,而 為這個結尾在最右邊的迴文子字串的中心點,也就是:。
先寫一個 function 來方便等等的計算, 表示從 往左和 往右的最長對稱字串長度,也就是說:令 ,,且 盡可能地大。
如果我們已經算好了前 項,現在要算第 項,我們會遇到幾種狀況:
最後,只要算怎麼把最大的 轉成 中最大迴文子字串的長度就好了。我們知道 的每一個字元在 中,前方都會有一個字元 ,而 最後也有一個 ,剛好以 為中心的最長迴文,兩端也會是 ,所以我們可以用一樣的想法來轉回去:令以 為中心的最長迴文長度為 ,轉回去 的長度就是 (注意 必為奇數),化簡後得到 。
仔細觀察會發現,這個過程只是不斷把 往右移,因此複雜度是漂亮的 。