最長回文(馬拉車演算法模板解析)

2021-10-23 11:00:15 字數 1904 閱讀 9909

最長回文

給出乙個只由小寫英文本元a,b,c…y,z組成的字串s,求s中最長回文串的長度.

回文就是正反讀都是一樣的字串,如aba, abba等

input

輸入有多組case,不超過120組,每組輸入為一行小寫英文本元a,b,c…y,z組成的字串s

兩組case之間由空行隔開(該空行不用處理)

字串長度len <= 110000

output

每一行乙個整數x,對應一組case,表示該組case的字串中所包含的最長回文長度.

sample input

aaaa

abab

sample output

4

3

解析:

什麼是馬拉車演算法:

比較官方的介紹,manacher(馬拉車)演算法是查詢乙個字串的最長回文子串的線性演算法。

我的理解就是從字串的開始,到末尾結束,找到當前右邊界最大的回文串子串,記錄對稱中心id和右邊界mx,利用對稱性,給下乙個以i為對稱中心的回文子串賦個初值p[i],以減少時間,之後再以i為對稱中心,在p[i]的基礎上向兩邊遍歷,找到以i為中心的最大回文子串的半徑p[i],之後更新id和mx。

字串的重構:

由於回文串分為奇回文串和偶回文串,為避免這種差異,可將乙個初始的字串用乙個不會出現的字元隔開,例如#a#b#a#,#a#b#b#a#,此時重構的回文串都是奇回文串,在重構的字串前面加乙個不同於間隔字元並且原字串中不會出現的字元,使字串從下標1開始。

int l=

0,i;

a[l++]=

'$';

//使字串從1開始

a[l++]=

'#';

//重構陣列,使其都變成奇數串

for(i=

0;i)a[l]=0

;//清空末尾

核心**的講解:

用p[i]陣列表示以i為回文中心時最長回文串的半徑

從重構的字串開頭開始遍歷,首先找到當前右邊界最大的回文串子串,記錄對稱中心id和右邊界mx,假設左邊界為mn,則對於下乙個i(此時i在id右面)有兩種情況,一種是對於以id為對稱中心,i的對稱點j=2*id-i,i+p[j]mx,即以j為中心的最大回文串左邊界小於mn,此時再利用以id為中心的最大回文串的對稱性只能得到i到mx之間的這一段是回文子串,所以此時p[i]=mx-i,(p[j]>mx-i)。之後在以上初值的基礎上再判斷a[i+p[i]]與a[i-p[i]是否相等,若相等則p[i]++,一直判斷,知道不相等為止,最後更新id和mx即可。

int mx=

0,id=0;

for(i=

0;i)}

完整**如下:

#include

"stdio.h"

#include

"string.h"

#include

"algorithm"

using namespace std;

char a[

200010

],s[

100010];

int p[

200010];

//p[i]為以i為回文中心時最長回文串的半徑

void

manacher

(int len)

a[l]=0

;//清空末尾

int mx=

0,id=0;

for(i=

0;i}int

main()

return0;

}

最長回文 馬拉車演算法

總時間限制 10000ms 單個測試點時間限制 1000ms 記憶體限制 5120000kb描述 給出乙個只由小寫英文本元a,b,c.y,z組成的字串s,求s中最長回文串的長度.回文就是正反讀都是一樣的字串,如aba,abba等 輸入乙個檔案一組資料 每組輸入為一行小寫英文本元a,b,c.y,z組成...

最長回文串(馬拉車演算法)

最長回文子串 manacher演算法 馬拉車演算法 馬拉車演算法需要計算以每個字元為中心的回文串半徑。並記錄最右邊界 馬拉車演算法基於這樣乙個事實,從回文串的中心到兩邊是對稱的,意味著以兩邊對稱的字元為中心的回文串半徑相等 在不超過最右邊界的情況下,如果超出就需要擴充套件搜尋 public stri...

最長回文串 馬拉車演算法

有兩個長度均為n的字串a和b。可以從a中選乙個可以為空的子串a l1 r1 b中選乙個可以為空的子串b l2 r2 滿足r1 l2,然後把它們拼起來 a l1 r1 b l2 r2 求用這樣的方法能得到的最長回文串的長度。注意 求的不是本質不同的回文串個數哦!解題報告 找兩個之間的最長回文串,只不過...