Manacher 字串回文查詢演算法說解

2021-07-15 16:35:30 字數 1984 閱讀 4670

manacher演算法是一種線性時間複雜度的字串回文查詢演算法,可以查詢給定字串內所有的回文串。時間複雜度 o(n),空間複雜度 o(n),其中 n 為字串的長度。

對於回文串而言,存在長度為奇數的回文串和長度為偶數的回文串,而增加了程式設計複雜度。而我們可以將字串中每相鄰的兩個字元間增加乙個特殊字元來解決這個問題。這樣,字串的長度變為 2 * n + 1 且所有的回文串的長度都為奇數,我們可以依次對每個字元搜尋以其為中點的回文串。

舉個例子:當字串為 「ababcbaabc」 時,我們通過把它處理成 「#a#b#a#b#c#b#a#a#b#c#」 (在這裡假定特殊字元為 『#』,當然只要滿足不可能在原字串中出現的字元都可以作為特殊字元,且乙個字串中只能出現一種特殊字元)來解決字串長度奇偶性的問題。這樣原字串中長度為偶數的回文串轉變為以特殊字元 『#』 為中點的長度為奇數的回文串。

為了本文敘述的方便起見,記原字串為 str[0 .. n - 1],新字串為 s[0 .. 2 * n-2]。對於新字串 s 而言,s[2 * i + 1] = str[i]。

manacher演算法闡述的是這樣乙個思想:當我們搜尋到下標 i 時,我們已經記下以下標 j(0 ≤ j ≤ i - 1) 為中點的最長回文字串的長度為 2 * p[j] -1,即已經找到乙個最大的 p[j] 使得 s[j - p[j] +1 .. j + p[j]-1] 為乙個回文串。同時,我們記下下標 id 和下標 id_max 使得 id + p[id] = id_max 且 j+ p[j] ≤ id_max(0 ≤ j ≤ i - 1)。這時,我們必得到 p[i] ≥ p[2 * id - i]。

證明如下:

已知 s[id - p[id] + 1 .. id + p[id] - 1] 為回文串,

則 s[i - p[2 * id - i] + 1 .. i + p[2 * id - i] - 1] = s[2 * id - i + p[2 * id - i] - 1 .. 2 * id - i - p[2 * id - i] + 1] (注意,此時等式右邊的式子當表示為 s[k .. l] 時 k > l,即在這裡我們設等式右邊的式子為 s[l .. k] 的翻轉串),

又由於s[2 * id - i - p[2 * id - i] + 1 .. 2 * id - i + p[2 * id - i] - 1] 為回文串,

所以s[i - p[2 * id - i] + 1 .. i + p[2 * id - i] - 1] = s[2 * id - i - p[2 * id - i] + 1 .. 2 * id - i + p[2 * id - i] - 1],(注意,此時等式右邊的式子當表示為 s[k .. l] 時 k < l,與上文不同)

故s[i - p[2 * id - i] + 1 .. i + p[2 * id - i] - 1] 為回文串,

即得到 p[i] ≥ p[2 * id - i]。

或許演算法到這裡就結束了,但是我們是否可以簡化一下呢?比如,我們是否可以不用實際把特殊字元插入,直接對原字串 str 操作來構建 p 陣列呢?

n := str. length

ans := id := id_max := 0

p[0] := 1

for i := [1, 2 * n)

p[i] := 1 + i mod 2

if i < id_max

p[i] := min(p[2 * id - i], id_max - i)

while str[i / 2 - (p[i] + 1) / 2] = str[(i - 1) / 2 + (p[i] + 1) / 2]

p[i] := p[i] + 2

if i + p[i] > id_max

id := i

id_max := i + p[i]

ans := max(ans, p[i] - 1)

由於 id_max 單公升,且僅當 i + p[2 * id - i] = id_max 時有 p[i] > p[2 * id - i]。故其線性時間得證。

Manacher演算法 求字串中最長回文串

manacher演算法在對求字串中最長回文串問題中,具有o n 時間和空間複雜度。演算法的精妙之處在於巧妙的利用了回文串的對偶性質。第一步 對字元間新增間隔符,例如,字串aababcdab,通過新增間隔符轉化為 a a b a b c d a b 從而避免了字串的奇偶性問題,為了避免演算法中考慮邊界...

字串的最長回文子串 manacher演算法

字串概念 回文子串概念 通常我們熟知的求解字串的最長回文字串的方法有以下兩種演算法 1 o n 2 列舉子串的左右兩個端點 o n 判斷該子串是否為回文串 總複雜度o n 3 2 o n 列舉每乙個回文子串的中點 偶數長度類似,不做討論 o n 向兩端拓展 總複雜度o n 2 如果將上述演算法2視為...

Manacher演算法 馬拉車(麻雀) 字串回文

這個演算法。和原先學習的kmp都是處理字串的。只不過麻雀是專門針對回文串的。我是最近cf補題的時候碰到這個演算法的。特此記錄一下。說實話。原先學資料結構的時候學的kmp。現在應該完全忘光了把。啊哈哈。明天再補補。舉個例子 回文串分為奇回文和偶回文。奇回文的中心是中間的字元。偶回文的中心是兩個字元中間...