馬拉車演算法

2021-10-04 02:13:18 字數 1798 閱讀 2575

馬拉車演算法是一種計算最長回文子串的演算法,以其優秀的線性複雜度聞名於世,相較於o(n

2)

o(n^2)

o(n2)的dpdp

dp演算法和會被特殊資料卡到o(n

2)

o(n^2)

o(n2

)的暴力演算法,馬拉車演算法無疑是求解最長回文子串的最優選擇。

最長回文子串分為偶數串和奇數串,為了避免這些問題,馬拉車演算法將每個字元與字元間插入乙個特殊字元,在兩頭插入不同的字元,以免越界。

馬拉車演算法定義:r

rr為當前已知的對稱的最右邊的點,mid

midmi

d為rr

r的對稱軸,f

if_i

fi​為以i

ii為對稱軸的最長回文子串的回文半徑

則我們遇到乙個i

ii,分兩種情況討論

若m id

≤i≤r

mid \leq i \leq r

mid≤i≤

r,則f

if_i

fi​可能為他的對稱點,即fmi

d∗2−

if_

fmid∗2

−i​,但如果i+f

mid∗

2−

ii+f_

i+fmid

∗2−i

​大於了r

rr,則就不能保證它的正確性,而能保證正確性的區域在哪兒呢?只有r

rr以內,所以要和r−i

+1

r-i+1

r−i+

1取乙個min

minmi

n,然而我們不能保證它的最長回文子串一定是這個範圍,所以我們要暴力拓展一下,直到不能拓展為止。

若r

r<

i,那麼暴力拓展即可。

而做完這一切後,看看r

rr和mid

midmi

d有沒有要更新的。

而我們統計答案時一定要減掉插入的字元,我們發現,統計出來的回文半徑一定是乙個奇數,則結尾是乙個#

\##,將對面的對過來,得到答案為fi−

1f_i-1

fi​−

1最終答案即為min

(fi)

−1

min(f_i)-1

min(fi

​)−1

那麼馬拉車演算法的時間複雜度是怎麼證明為線性呢?

若是m id

≤i≤r

mid \leq i \leq r

mid≤i≤

r且取值為fmi

d∗2−

if_

fmid∗2

−i​,那麼是一定不會拓展的,因為這還在這個回文半徑裡面,兩邊肯定是相同的

而其他兩種情況,r

rr是一定隨著動的。所以複雜度為線性,即o(n

)o(n)

o(n)

**實現:

#include

#include

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)<(b)?(a):(b))

using

namespace std;

int n,m,k,f[

2000039

],mr,mid,ans;

char s[

2000039

],x;

intmain()

printf

("%d\n"

,ans)

;}

馬拉車演算法

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

馬拉車演算法

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 題意在給定的字串中找...

馬拉車演算法

馬拉車演算法查詢 字串的最大回文子串。其演算法本質上是中心擴充套件法。中心擴充套件法 vectorv strlen,0 v i 是指以i為中心的回文字串長度的半徑 for int i 1 i strlen 1 i while str i 1 v i str i 1 v i v i 不考慮越界 而馬拉...