Manacher最長回文串演算法

2021-08-21 13:31:18 字數 1865 閱讀 4058

在介紹演算法之前,首先介紹一下什麼是回文串,所謂回文串,簡單來說就是正著讀和反著讀都是一樣的字串,比如abba,noon等等,乙個字串的最長回文子串即為這個字串的子串中,是回文串的最長的那個。

一.通常解決的問題

給定乙個字串,求出其最長回文子串。例如:

(1)s="abcd", 最長回文長度為 1;

(2)s="ababa", 最長回文長度為 5;

(3)s="abccb", 最長回文長度為 4,即 bccb。

經典例題:hdu3068

以上問題的傳統思路大概是,遍歷每乙個字元,以該字元為中點向兩邊查詢。其時間複雜度為 o(n2),很不高效。而在 1975 年,乙個叫 manacher 的人發明了乙個演算法,manacher 演算法,也稱馬拉車演算法,該演算法可以把時間複雜度提公升到 o(n)。下面來看看馬拉車演算法是如何工作的。

二.演算法原理

奇偶變換:為處理字串方便,現將給定的任意字串進行處理,使所有可能的奇數/偶數長度的回文子串都轉換成了奇數長度。具體就是在每個字元的兩邊都插入乙個特殊的符號。比如hhjj變成 #h#h#j#j#, aba變成 #a#b#a#;為防止陣列越界,可以在字串的開始加入另乙個特殊字元,比如「?#a#b#a#?」 。

定義乙個輔助陣列int pp[i]表示以s_new[i]為中心的最長回文的半徑,例如:i0

1234

5678

9101112

1314

1516

1718

19s_new[i]$#

a#b#

b#a#

h#o#

p#x#

p#p[i]12

1452

1212

1212

1612

1 可以看出,p[i]-1正好是原字串中最長回文串的長度。

manacher 演算法之所以快,就快在對 p 陣列的求法上有個捷徑,看下圖:

設定兩個變數,mx 和 id 。

mx 代表以s_new[id]為中心的最長回文最右邊界,也就是mx=id+p[id]

假設我們現在求p[i],也就是以s_new[i]為中心的最長回文半徑,如果i2 * id -i其實就是等於 j ,p[j]表示以s_new[j]為中心的最長回文半徑,見上圖,因為 i 和 j 關於 id 對稱,我們利用p[j]來加快查詢。

#include#include#include#includeusing namespace std;

const int maxn=111111;

char s[maxn];

char s_new[maxn*2];

int p[maxn*2];

int init()

s_new[j] = '\0';

//printf("%s\n",s_new);

return j; //返回s_new的長度

}int manacher()

maxlen = max(maxlen, p[i] - 1);

// printf("%d %d %d\n",mx,id,maxlen);

}/*for(int i=1;i<=len;i++)printf("%d ",p[i]);

printf("\n");*/

return maxlen;

}int main()

manacher演算法(最長回文串)

題目解釋 子串 小於等於原字串長度由原字串中任意個連續字元組成的子串行 回文 關於中間字元對稱的文法,即 aba 單核 cabbac 雙核 等 最長回文子串 1.尋找回文子串 2.該子串是回文子串中長度最長的。首先要知道這個演算法是用來在o n 的時間裡看乙個字串的最長回文子串的長度是什麼。其次,它...

Manacher演算法 最長回文串

若字串長度為n,則演算法的時間複雜度為o n 假設有乙個字串abaaba 先把該字串變成 a b a a b a 第乙個字元設為 防止計算的時候陣列越界 再計算p陣列,先給出p陣列的答案 i為座標,ma陣列放改變後的字串,p陣列代表以該字元為中心,向右和向左延伸p i 個,是回文串 i 0 1 2 ...

最長回文字串(manacher演算法)

資料 網路 參見 問題描述 輸入乙個字串,求出其中最大的回文子串。子串的含義是 在原串中連續出現的字串片段。回文的含義是 正著看和倒著看相同,如abba和yyxyy。解析 這裡介紹o n 回文子串 manacher 演算法 演算法基本要點 首先用乙個非常巧妙的方式,將所有可能的奇數 偶數長度的回文子...