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

2021-10-04 05:50:09 字數 2201 閱讀 3909

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

舉個例子:

回文串分為奇回文和偶回文。奇回文的中心是中間的字元。偶回文的中心是兩個字元中間的位置。不好同一處理。

所以我們加如下操作。比如aabbaa

增加為#a#a#b#b#a#a#

這樣不管是奇回文還是偶回文都是字元啦。偶回文是#。奇回文還是原來的。

我們用陣列p儲存當前下標index作為中心時的回文序列長度半徑

所以我們以當前下標index為中心的回文串的最長長度就是p[i] - 1(這個地方不證明了。自己隨便舉幾個例子就明白了)

mx記錄當前已操作序列的最右的回文邊界。就是最長的回文序列的最右邊的地方。

id記錄最長回文序列的中心位置。

當我們遍歷到i時。求p[i]

我們找到i的對稱點j。這個地方的下標很簡單求出來。(id - (i - id))即可

如圖所示mx的對稱點也標出來了。上面解釋了。mx是最優邊界。id是最長回文串的中心。

p[j]我們已經求出來了。

本演算法的核心**:

上面的p[2*id - i]就是p[j];

我們討論一下p[j]的大小。

如果p[j]的回文串只有這麼長。

也就是沒有大於mx - i的長度

圖中標記的橙色部分相等。。這個簡單。

也就是以j為中心得回文串沒有超過這個長度。

因為對稱。所以此時我們賦值p[i] = p[j];這個是此時p[i]的最小長度。就在這個地方節約時間的。

至於p[i]的值有沒有可能更長。我們後面暴力跑一遍就行。

如果p[j]的回文串大於了這個長度。

也就是這樣:

已經超過了mx的對稱點的長度。

那我們只能將p[i]賦值為mx - i

因為這個mx - i是我們現在已知的最小長度。

因為mx對稱點左邊的字元和mx右邊的字元不等呀。不然mx肯定不在當前位置了。。

之後我們暴力跑一遍判斷即可。

我當時在想為啥這兩部分的p是一一對稱的。

傻坐在那想了半天。。

後來舉了個例子畫了個圖就知道了。

因為mx和mx對稱點範圍內就是我們求得最長回文呀。id左邊和id右邊肯定是一一對稱的呀。。。害~

上面解釋完了就應該很好理解了。

然後我們在製作新的字串的時候注意邊界位置。

第乙個字元初始化為$

最後乙個字元就是結束標誌』\0』就行。避免溢位。

時間複雜度控制在o(n)範圍

棒~模板**:

我最後輸出的是最長的回文串的長度。

#include

using

namespace std;

const

int n =

2e7+10;

string s;

char ss[n]

;int p[n]

;int

init()

//形成新的字串

ss[i]

='\0'

;return i;

}int

manacher()

else

while

(ss[i - p[i]

]== ss[i + p[i]])

if(mx < i + p[i]

) maxx =

max(maxx, p[i]-1

);}return maxx;

}int

main()

Manacher 馬拉車演算法

給定乙個字串,求出其的最長回文子串 乙個將時間複雜度優化到o n 的演算法 暴力演算法,但不是純暴力,即按照做過的事情不再去做來優化 我們知道,乙個回文串要麼是奇數的串 aba 要麼是偶數的串 abba 可以看出,乙個回文串有乙個對稱軸 對於奇數串aba來說,對稱軸就是b 而對於偶數串abba來說,...

Manacher演算法(馬拉車)

演算法總結第三彈 manacher演算法,前面講了兩個字串相演算法 kmp和拓展kmp,這次來還是來總結乙個字串演算法,manacher演算法,我習慣叫他 馬拉車 演算法。相對於前面介紹的兩個演算法,manacher演算法的應用範圍要狹窄得多,但是它的思想和拓展kmp演算法有很多共通支出,所以在這裡...

馬拉車演算法manacher

1.預處理解決奇回文和偶回文問題 比如 str bcbaa 在每個字元的開頭,結尾和中間插入乙個特殊字元 來得到乙個新的字串 b c b a a 這樣對於原來字串中的奇回文 bcb 來說,在新的字串中變成了 b c b 還是奇回文,只是回文串長度從3變成了7 注意 中 i 1 0,與1按位與,如果i...