Manacher(馬拉車)演算法

2022-07-30 05:21:15 字數 1866 閱讀 7023

英譯過來就是馬拉車

是乙個求乙個字串中最長回文連續子串行的演算法

例如abaabaabb最長的就是7

abaaaaba

最長就是8

ababbb最長就是3

注意:乙個字串可能不只有乙個最長回文連續子串行

傳統做法就是列舉中間點向兩邊擴充套件,時間複雜度是o(n^2)

然後這個演算法就優化到了o(n)

這是優化嗎,性質都變了啊喂

首先回文分為兩種:奇回文偶回文如果列舉的話,有時候是字元,有時候要列舉字元之間的位置,就很麻煩

為了操作方便(因為我們要定義以i為中心),我們把它們都變成奇回文

怎麼做呢?很簡單,全部插入乙個符號即可(沒出現過)

例如  

abaababa ——> (#a#b#a#a#b#a#b#a#)

前後是防止越界,你可以隨便定義(只要字串裡沒有的,不會衝突)

原來aba就可以變成#a#b#a#

原來baab就可以變成#b#a#a#b#

這樣一來就全部變成了奇回文啦!

我們定義p[i]是以i為中心的,最長回文串的半徑(包括自己)

字串(#a

#b#a

#a#b

#a#b

#a#)

p112

1412

7214

1214

1211

我們現在要做的就是o(n)處理出每乙個p[i]

考慮能不能根據之前已經得到的來推測出答案呢

當前我們列舉到i,已知有乙個以mid為中心的回文子串,其右端點到了mx

可知以mid為分界線,左右兩邊是完全對稱的(回文子串定義)

當i+p[j]

我們就可以直接更新答案,因為不可能更長了

當i+p[j]>=mx時

我們只能到mx這個位置,因為我們不知道mx後面是否還能繼續匹配

(只取紅色部分)

我們就可以根據i的對稱點j來更新答案,但是p[i]不一定等於p[j],因為mx後面的還是未知的,我們不知道,這一部分暴力匹配就是了

可知mx是一直在增大,每增大一次,我們需要比較一次,mx最多從0到n,所以也就是o(n)的複雜度

其實和kmp都有乙個運用已知答案的思想

最後輸出答案的時候我們半徑減一即可(可以自己手%一下找找規律)

1 #include2

using

namespace

std;

3char s_new[21000002];4

char s[11000002];5

int p[21000002];6

int init()

16 s_new[j]='\0'

;17return

j;18}19

intmanacher()

2036 ans=max(ans,p[i]-1);//

更新答案

3738}39

return

ans;40}

41int

main()

42

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...