最長回文子串Manacher演算法

2021-10-04 09:20:15 字數 1040 閱讀 9357

發現自己時間過久了就會忘掉 ... 寫一遍在這裡吧~

問題: 求乙個字串的最長回文子串. 

直觀思路, 每乙個回文子串都可以由"中心"和"半徑"來唯一決定, 如回文串"abcdbca"的中心是c, 半徑長度為3. (對於總長度為偶數的回文子串, 我們先想象其中心不是乙個字元, 而是字串中間的"間隙"; 以下討論中, 為便於分析, 暫時只考慮奇數長度的回文串)

按這個思路, 我們已經可以解決這個問題了: 對原字串的每個字元, 都把它當作中心來求最大半徑. 求最大半徑的過程就是乙個試圖拓展的過程, 不斷比較c-r和c+r處的字串是否相同. 

while (s[c+r] == s[c-r])
在此基礎上, 我們如果考慮到, 對於已知的回文串, 其中心的左右兩邊是對稱的, 那麼就可以發現有些字元比較是不必要的. 

如圖, 對於字串s, 在我們從左至右依次把每個位置都當作中心拓展最長回文子串的過程中, 假設綠色部分是已知的回文串, 現在考慮中心c2. 那麼, 注意到以c為中心的綠色左右兩邊的對稱的. 我們可以關注一下c2的對稱點c1, 如果c1的半徑是r1, c2的半徑至少也是r1, 可以節省r1次比較. 

// maxcover:最右邊界 maxc:最右邊界對應的中心 r:每個點作為中心的半徑

curr = 1;

if (c2 < maxcover)

while (s[c2 - curr] == s[c2 + curr])

curr = curr - 1;

// 維護 maxcover 等

最後, 為了避免奇偶性的討論(也就是中心是字元還是字元之間的間隙), 以及省去對字串邊界的條件判斷, 對原字串進行一次預處理: 在每兩個字元中間都插入乙個原串中未出現過的特殊字元, 並在字串開頭另加乙個特殊字元. 

如插入'#'和'@'將"abaa"變為"@a#b#a#a".

這就是manacher演算法. 

O n 時間求 最長回文子串 Manacher演算法

回文字串分為奇回文和偶回文,在字串中間插入任意字元使得串變成奇回文串 暴力思想 肯定是找乙個點往兩邊任意擴充套件,遍歷一次,manacher時間為o n 開乙個陣列p記錄 以點i為中點 的最長回文串的半徑,假設前i 1個點的p都已經求出來來,現在考慮p i 如何推導 重點 r是p 1 p i 1 中...

Manacher 最長回文子串

最長回文子串問題 給定乙個字串,求它的最長回文子串長度。如果乙個字串正著讀和反著讀是一樣的,那它就是回文串。下面是一些回文串的例項 12321 a aba abba aaaa tattarrattat 牛津英語詞典中最長的回文單詞 對於最長回文子串問題,最簡單粗暴的辦法是 找到字串的所有子串,遍歷每...

Manacher 最長回文子串

caioj任意門 hz2016評測傳送門 可以的話來一下hz2016評測吧,有的題caioj沒有的我也可以給到資料嘛。include include include include include include include include define maxchar 100000 defin...