最大回文串 Manacher演算法

2021-10-05 05:36:14 字數 1472 閱讀 3290

manacher演算法是針對於字串的乙個處理演算法,目的在於求解乙個字串的最大回文串。它的時間複雜度為o(n)。求解乙個字串的最大回文串最容易想到的就是從乙個字串出發將其作為中心,依次向兩端擴充套件,直到遇到不同的字元。這種演算法的最壞時間複雜度可以達到o(n^2),除此之外對於偶數長度的最大回文串需要另行討論,因此不是最佳的解法。

如上所述,manacher演算法對於偶數長的回文串存在一定的限制。對於這一點,manacher演算法採取的措施是,將原字串首、尾包括字元之間插入乙個標記的字元。這個字元不能在原字串**現。(舉例,如原字串為ab,則改變後的字串為#a#b#)manacher演算法之所以這樣做,是因為這樣可以將偶數回文串和奇數回文串全部統一為奇數回文串,便於處理。之後我們就可以通過先求新串的結果,再來處理原串以此得到答案。

在kmp演算法裡,我們知道可以用之前得到的結論來取消某些不必要的遍歷來降低時間成本,這裡同樣採取類似的思路。我們可以維護乙個陣列p,p[i]的含義是以第i個字元為中心,最大的回文串的半徑長度。例如:對於原串abcb,我們將其處理為#a#b#c#b#,它的p陣列為i1

2345

6789

字元#a#

b#c#

b#p[i]12

1214

121那麼p陣列應該如何維護呢?我們定義乙個變數id,令p[id]為已維護的p[i]中的最大值。令mx = id + p[id],即為該最長回文串的右邊界。在遍歷過程中,會出現如下的兩種情況:

1、當前所處的位置i已經超過了mx。此時,由於前面的字元我們並沒有接觸過,因此只能老老實實從i出發,向兩側擴充套件,直到字元不同後停止並修改當前p[i]的值。

2、若當前的位置i在mx左側,即i < mx,則會出現下圖的狀況:

從這裡不難看出,j若為i關於id的對稱點,則它的座標為j = 2*id - i。此時p[i]具有乙個最小值,如果對於p[j]來講,它的最左端沒有超出id對應字串的左邊界(就是mx的對稱點),則根據對稱性,p[i] = p[j]。否則,由於超出id右側的部分我們並不確定是否對稱,因此p[i]有最小值:j - mx對稱點。即mx - j。之後回到第一種情況向兩邊遍歷修改p[i]即可。

最後在得到最大值p的最大值most後,我們只需要將(most*2-1)/2(乘2再-1將長度變為新串裡最大回文的長度,除以2回到原串最大的長度)就可以得到原串的最大回文串的長度了。

#include#include#includeusing namespace std;

int id,j;

char str[10000],a[10000];

int p[10050];

void getnew()

if(most < p[i])//尋找p的最大值

most = p[i];

} return most;

}int main()

}

最大回文字串長度 manacher演算法

參考 題目 hdu3068 hdu3068.cpp 定義控制台應用程式的入口點。include stdafx.h include include include include using namespace std int longestpdr vector vc for int i 0 i rd...

最大回文子串manacher演算法python

關於最大回文子串問題,有兩種處理方法 1.以每個字元為中心,向兩邊尋找回文子串,遍歷整個陣列後,返回最長的。該方法時間複雜度較大為o n 2 2.乙個中等難度的動態規劃演算法 馬拉車 step1 給每個字元左右都加上特殊字元比如 處理後,能使字串s長度為奇 step2 現在的問題變成如何高效求得rl...

(回文串)Manacher演算法

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