manacher 馬拉車 演算法簡單講解

2021-10-03 12:06:13 字數 3155 閱讀 6330

介紹:manacher是一種用來求字串子串中最長回文長度,時間複雜度可以達到o(n

)o(n)

o(n)

級別。下面先介紹暴力求解法。

思路

①求出字串的所有子串,時間複雜度為o(n

2)o(n^2)

o(n2

)。設定指標lef

t,ri

ghtleft,right

left,r

ight

,分別表示子串的左右下標,在第乙個for迴圈列舉出所有可能的lef

tleft

left

,在第二個for迴圈列舉出在lef

tleft

left

情況下,所有可能的rig

htright

right。

②判斷字串為回文字串的方法,時間複雜度為o(n

)o(n)

o(n)

。把字串翻轉,與原來字元比較如果相同即為回文字串。

源**

bool

ispalindromes

(string s,

int,

int)

;void

findsubstring

(string s)}}

}

前方高能!!下面進入正文

原理:對於奇數長度的字串,如s="

abcb

a"s="abcba"

s="abc

ba",肯定有乙個中心位置,如c

cc,左右分別是對稱的區域,如果從第0個開始遍歷,就會有乙個時時更新的最右回文字元。比如,從第乙個a開始最右的回文字元是是s[0

](a)

s[0] (a)

s[0](a

),到c時最右字元是s[4

](a)

s[4](a)

s[4](a

)。可能有人會問了這樣做有什麼用,接下來我就介紹如何利用這個最右邊界。

假設這個最右邊界為max

nmaxn

maxn

,這個最右邊界的中心為cen

tercenter

center

,當前位置的下標為ser

vial

servial

servia

l。①如果ser

vial

servial

servia

l位於這個最右邊界內,即ser

vial

xnservialse

rvialxn

,根據對稱我們可以找到左邊的字母,如前面字串中s[4

]as[4]a

s[4]

a對應s[0

]as[0]a

s[0]a。

根據前面的字母我們可以知道該字母的回文長度,如果長度的一半−1-1

−1沒有超過左邊界,那麼很明顯右邊字母的回文長度等於左邊的那個,這裡畫**釋一下吧。

如果超過了左邊界,那麼就是說左邊字母有些字元是不包含在這個最右的回文字元中的,所以我們只能先確定一部分回文字元(最右的座標減去ser

vial

∗2+1

servial*2+1

servia

l∗2+

1),而右邊的無法確定。

②如果ser

vial

servial

servia

l本來就不在最右字串裡面,就可以先讓它的回文長度為1

11,然後開始向搜尋。這個應該好理解,就不畫圖了,有不懂的dd我。

這兩種進行更新時,如果超過了回文字串的最右邊界,記得更新邊境。

如果你以為這樣就玩了,那你就錯了,如果是字串是偶數個時,我們是找不到,所謂的cen

tercenter

center

,所以我們在每乙個字元中間插入乙個字串沒有的字元如∗

*∗,最後還在開頭跟結尾插入另兩個字元作為哨兵。因此具體的做法也要稍稍調整一下,我們只用紀錄長度的一半就好,因為有一半是無關的字元∗*∗。

如我們把aba

abaab

a,變為∗a∗

b∗a∗

*a*b*a*

∗a∗b∗a

∗,長度由3

33變到了7

77,其實我們只要記錄b

bb和後面的長度即可,為4

44,4−1

4-14−

1即為正確結果。

對於偶數個的如aaaa

aa,變為∗a∗

a∗*a*a*

∗a∗a

∗,記錄一半的長度為3

33,3−1

3-13−

1,ok

!ok!

ok!

最後分別給一下兩部分的函式

int
transform

(char

*ori)

cur[

2*len+1]

='*'

; cur[

2*len+2]

='$'

;//哨兵

cur[

2*len+3]

='0'

;//字串結束的標誌

return

2*len+1;

}int

manacher

(char

*cur,

int len)

ans=

max(ans,len[t]);

}return ans-1;

//由於補充字元的結果,在紙上畫一下很容易看出來的ok!

ok!ok

!搞定,我寫部落格的目的主要是為了鞏固知識,所以有部分會借鑑一下。

部分引用於這。

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