英譯過來就是馬拉車
是乙個求乙個字串中最長回文連續子串行的演算法
例如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 #include2using
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...