Manacher演算法 求字串中最長回文串

2021-07-03 21:18:43 字數 1891 閱讀 3736

manacher演算法在對求字串中最長回文串問題中,具有o(n)時間和空間複雜度。演算法的精妙之處在於巧妙的利用了回文串的對偶性質。

第一步:對字元間新增間隔符,(例如,字串aababcdab,通過新增間隔符轉化為 #a#a#b#a#b#c#d#a#b#)從而避免了字串的奇偶性問題,為了避免演算法中考慮邊界問題,可以在字串首尾加入奇異符號(例如,$#a#a#b#a#b#c#d#a#b#&,因為c/c++字串中有結束符\0,所以可可以省略尾端加入的奇異符);

第二步:更新模式陣列p,這裡也是manacher演算法的核心所在,我當初看這塊時糾結了好長時間。首先通過來說明一下:

假設當前處理位置在i點,且 i < mx(mx為關於座標k對稱子串的右邊界為),即p[k] = mx - k。此時忽略左邊界mx』又 i 關於 k 對稱的座標為 j ,這時就可以分成兩種情況:

p[j] > mx - i + 1 時,p[i] = mx - i + 1;因為 mx 和 mx』 ,i 和 j 為關於k對稱,所以 s[ mx』, ~ ,j ] = s[ i, ~ ,mx ]。如果 p[i] > mx - i + 1,也即 s[mx+1] = s[2*i - mx - 1],而已知:s[mx』 -1] = s[2*j - mx』 + 1 ],j + i= 2*k,mx』 + mx= 2*k ,所以有s[mx』-1] = s[mx+1],這時以k為中心對稱子串右邊界變為了mx+1,矛盾。

p[j] == mx - i + 1 時,p[i] >= p[j];證明方法和上面一樣。

p[j]

對於其他情況就需要重新匹配了。

第三步:找到(也可以在更新p時記錄最大數)模式陣列p中最大數減一,即為字串中最大回文串長度。

#include 

#include

using

namespace

std;

int longestpalindromicsubstring(const

string& s, int& maxpos)

else

if( recompute )

if( p[i] > maxlength)

if(i + p[i] > mx)

cout

<< s[i] << " ";

recompute = false;

}cout

<< endl;

for(int i = 1; i < s.size(); i++)

cout

<< endl;

maxpos = maxpos/2 - 1 - --maxlength/2;

delete p;

return maxlength;

}int main()

cout

<< s_process << endl;

int pos = 0;

int length = longestpalindromicsubstring(s_process, pos);

cout

<< "max longest palindromic substring is : "

<< s.substr(pos, length) << endl;

cout

<< "max length : "

<< length << endl;

return

0;}

字串演算法manacher演算法

manacher是一種線性時間複雜度演算法,對於給定的字串s,可以在o n 時間內,求出以每個位置為中心的最長回文子串。插入無關字元 在相鄰字元之間以及字串首尾分別插入s中沒出現的字元,設為 得到str。則str中以任意位置為中心的最長回文串長度是奇數。記 p i max。因此只要求出p陣列即可。假...

字串專題小結 Manacher演算法求最長回文串

資料 網路 參見 有改動 這道題是一道經典的manacher演算法講解題目,manacher是時間複雜度為o n 的演算法。比起蠻力法 對於o n 的每乙個點,都掃瞄該點的左右對稱點,這種方法效率顯然是o n 2 的 演算法巧妙之處 首先用乙個非常巧妙的方式,將所有可能的奇數 偶數長度的回文子串都轉...

O n 求回文串 manacher演算法

p id 2 i 代表的是關於i關於id對稱的點j,陣列p i 1代表插入字元後一i問對稱的回文串的長度 資料 網路 參見 問題描述 輸入乙個字串,求出其中最大的回文子串。子串的含義是 在原串中連續出現的字串片段。回文的含義是 正著看和倒著看相同,如abba和yyxyy。解析 這裡介紹o n 回文子...