Manacher s 馬拉車 演算法

2021-10-01 03:12:20 字數 1600 閱讀 1481

manacher』s algorithm,中文名叫馬拉車演算法,是一位名叫manacher的人在2023年提出的一種演算法,解決的問題是求最長回文子串,神奇之處在於將演算法的時間複雜度精進到了o(n),下面我們來詳細介紹下這個演算法的思路。

馬拉車演算法本質還是中心擴散,為了避免回文串是奇數還是偶數的情況,要對原始的回文串字元進行新增分隔符操作。

第一步:新增分隔符

假設分隔符為「#」,在字串「ababa」中新增後的結果是「#a#b#a#b#a#」。即新增後是結果字串的總數是奇數的

第二步:計算輔助陣列

輔助陣列的作用就是記錄以每個字串為中心的回文串的資訊。

輔助陣列中的值,就是以當前的字元為中心,同時向兩邊進行擴散乙個位置,若兩邊相同,則繼續擴散,一直等到不相同為止,在當前字元的值中記錄下向兩邊擴散的位置大小。

例如圖中3下標的字元,以 char[3] = 『b』 為中心,同時向左邊向右擴散,走 1 步,左右兩邊都是 「#」,構成回文子串,繼續同時向左邊向右擴散,左邊是 「a」,右邊是 「b」,不匹配,最多能擴散的步數為 1 ,因此 p[3] = 1;

這種情況的輔助陣列會導致一種計算錯誤的結果。

馬拉車演算法詳解

那麼下面我們就來看如何求p陣列,需要新增兩個輔助變數 mx 和 id,其中 id 為能延伸到最右端的位置的那個回文子串的中心點位置,mx 是回文串能延伸到的最右端的位置,需要注意的是,這個 mx 位置的字元不屬於回文串,所以才能用 mx-i 來更新 p[i] 的長度而不用加1,由 mx 的更新方式 mx = i + p[i] 也能看出來 mx 是不在回文串範圍內的,這個演算法的最核心的一行如下:

p[i]

= mx > i ?

min(p[

2* id - i]

, mx - i):1

;

#include 

#include

#include

using namespace std;

string manacher

(string s)

// process t

vector<

int>

p(t.

size()

,0);

int mx =

0, id =

0, reslen =

0, rescenter =0;

for(

int i =

1; i < t.

size()

;++i)

if(reslen < p[i])}

return s.

substr

((rescenter - reslen)/2

, reslen -1)

;}intmain()

馬拉車演算法

思路筆記 上述情況1和情況2又可以歸結為 i 的回文半徑 和 r i的距離 中小的那個就是i的回文半徑。include include includeusing namespace std string manacherstring string str return res int min int...

馬拉車演算法

馬拉車演算法是一種計算最長回文子串的演算法,以其優秀的線性複雜度聞名於世,相較於o n 2 o n 2 o n2 的dpdp dp演算法和會被特殊資料卡到o n 2 o n 2 o n2 的暴力演算法,馬拉車演算法無疑是求解最長回文子串的最優選擇。最長回文子串分為偶數串和奇數串,為了避免這些問題,馬...

馬拉車演算法

manacher char s maxn 1 int n,hw maxn 1 int l maxn 1 r maxn 1 void manacher char a n len 2 2 s n 0 int maxr 0,m 0 for int i 1 i n i manacher 題意在給定的字串中找...