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 回文子...