Manacher演算法C 實現

2021-10-08 14:56:47 字數 2141 閱讀 3907

manacher演算法也稱「馬拉車演算法」,是用來解決求字串的最長回文串的演算法。

對於求最長回文串有三種演算法:

1.暴力列舉法 優點:簡單易寫

缺點:複雜度過高(o(n^3))

string s;

cin >> s;

int maxlength =

1,start=0;

for(

int i =

0; i < s.

size()

; i++)}

if(temp1 >= temp2 && j -1+

1> maxlength)}}

cout << s.

substr

(start, maxlength)

;

2.由中間展開,分為奇偶數兩種情況

string longestpalindrome

(string s)

int imax=0;

int ileft=

0,iright=0;

for(

int i=

0;isize()

;i++

)--ltmp;

++rtmp;}if

(imax}int ltmp=i-

1,rtmp=i+

1while

(ltmp>=

0&& rtmpsize()

)--ltmp;

++rtmp;}if

(imax < rtmp-ltmp-1)

}}return s.

substr

(ileft,iright+

1-ileft)

;}

優點:降低複雜度

缺點:要分奇偶性

未充分利用前面查詢工作的結果

沒有思考回文字元本身的特性:

3.manacher演算法

#include

using

namespace std;

intmin

(int a,

int b)

//選取兩個數值之間最小值

}string manancher

(string s)

//預處理,將所有字串變為奇數個

string t =

"$";

//字串開頭先增加乙個特殊字元,防止越界

for(

int i =

0; i < s.

size()

; i++

) t +

="#@"

;//在字串尾部增加乙個特殊字元,表示結束(其實也可以不加,因為c++中string字串尾部自動新增'/0',表示結束)

cout << t << endl;

int n = t.

size()

;//求出新陣列的長度

int* p =

newint

[n];

//p陣列,用來求每乙個字元的回文串的半徑

int id =

0, mx =0;

//用來檢索並求p[i] 延伸到最右端位置的那個回文子串的中心點位置,mx是該回文串能延伸到的最右端的位置

int maxlength =0;

//回文串最長半徑

int index =0;

// 最長回文子串的中心位置索引

for(

int i =

1; i < n -

1; i++

)//從有效字元開始遍歷,求出p[i],並求出maxlength

// 如果回文子串的右邊界超過了mx,則需要更新mx和id的值

if(mx < p[i]

+ i)

// 如果回文子串的長度大於maxlength,則更新maxlength和index的值

if(maxlength < p[i]-1

)}int start =

(index - maxlength)/2

;return s.

substr

(start, maxlength);}

intmain()

**都上機執行通過測試,可放心食用~

Manacher演算法總結

所謂回文串,簡單來說就是正著讀和反著讀都是一樣的字串,比如abba,noon等等,乙個字串的最長回文子串即為這個字串的子串中,是回文串的最長的那個。下面介紹manacher演算法的原理與步驟。首先,manacher演算法提供了一種巧妙地辦法,將長度為奇數的回文串和長度為偶數的回文串一起考慮,具體做法...

Manacher演算法總結

演算法總結第三彈 manacher演算法,前面講了兩個字串相演算法 kmp和拓展kmp,這次來還是來總結乙個字串演算法,manacher演算法,我習慣叫他 馬拉車 演算法。相對於前面介紹的兩個 演算法,manacher 演算法的應用範圍要狹窄得多,但是它的思想和拓展kmp 演算法有很多共通支出,所以...

manacher演算法總結

原文 1 len陣列簡介與性質 manacher演算法用乙個輔助陣列len i 表示以字元t i 為中心的最長回文字串的最右字元到t i 的長度,比如以t i 為中心的最長回文字串是t l,r 那麼len i r i 1。對於上面的例子,可以得出len i 陣列為 2 len陣列的計算 首先從左往右...