manacher
一、背景
2023年,manacher發明了manacher演算法(中文名:馬拉車演算法),是乙個可以在o(n)的複雜度中返回字串s中最長回文子串長度的演算法,十分巧妙。
讓我們舉個栗子,栗子:
1.字串:abbababa 最長回文子串:5(abbababa)
2.字串:abcbbabbc 最長回文子串:7(abcbbabbc)
3.字串:abccbaba 最長回文子串:6(abccbaba)
傳統方法是,遍歷每個字元,以該字元為中心向兩邊查詢。時間複雜度為o(n^2),效率很差;
而這個神奇的manacher演算法將複雜度提公升到了o(n)。
來一起瞅一瞅它是如何工作的吧。
二、演算法過程分析
回文分為奇回文(ababa)和偶回文(abba),這裡比較難以處理,我們使用乙個小(sao)技(cao)巧(zuo)(很重要)。我們將字串首尾和每個字元間插入乙個字元(注意:這個自符在串中並未出現)例如:'#'.
栗子!栗子!
s='abbadcacda'先轉化成s_new='$#a#b#b#a#d#c#a#c#d#a#\0'('$'與'\0',是邊界,下面的**中可以看到)
這樣原串中的偶回文(abba)與奇回文(adcacda),變成了(#a#d#d#a#)與(#a#d#c#a#c#d#a#)兩個奇回文。
定義陣列p,用p[i]表示以i為中心的最長回文半徑。栗子在這裡:
那,p[i]該如何求呢?
很顯然,p[i]-1正好就是原字元中的最長回文串長度了。
讓我們一起找到正解。
請看下圖:
定義兩個變數mx和id。mx就是以id為中心的最長回文右邊界,也就是mx=id+p[id],隨後我們需要mx做出它的最大貢獻。
假設我們在求p[i](以i為中心的最長回文半徑),如果i
if(i2*id-i是i關於id的對稱點(上圖j)(證明:i-id=id-j),而p[j]表示以j為中心的最長回文半徑,這樣我們就可以利用p[j]和mx加快速度了。p[i]=min(p[2*id-i],mx-i);
為什麼要用p[j]和mx-i取min來更新,什麼鬼?
淡定,淡定。我們想一下,p[j](以j為中心的最長回文半徑)是已經知道了(因為是從前面掃過來的),若是p[j]>mx-i,我們是可以知道以j為中心,以mx的對稱點到j的距離為半徑形成的回文字串是肯定存在的,並且id的左邊直到mx的對稱點與id的右邊 直到mx是一一對應的,不難理解mx是i目前可以更新到的最大回文半徑;若p[j]取完min就是最大的回文半徑嗎?
顯然不是,接下來的暴力往後掃就好了(學oi的都有暴力傾向)。
三、**
#include#include四、複雜度 完結撒花(複雜度不會證明呀,因為我是蒟蒻)#include
#include
using
namespace
std;
char s[11000002];
char s_new[21000002];//
存新增字元後的字串
int p[21000002];
int init()
s_new[j]='
\0';//
處理邊界,防止越界(容易忘記)
return j;//
返回s_new的長度
}int manacher()
max_len=max(max_len,p[i]-1
); }
return
max_len; }
intmain()
Manacher(馬拉車) O n 回文子串
manacher 一 背景 1975年,manacher發明了manacher演算法 中文名 馬拉車演算法 是乙個可以在o n 的複雜度中返回字串s中最長回文子串長度的演算法,十分巧妙。讓我們舉個栗子,栗子 1.字串 abbababa 最長回文子串 5 abbababa 2.字串 abcbbabbc...
最長回文長度 manacher(馬拉車)
給出乙個只由小寫英文本元a,b,c y,z組成的字串s,求s中最長回文串的長度.回文就是正反讀都是一樣的字串,如aba,abba等 input 輸入有多組case,不超過120組,每組輸入為一行小寫英文本元a,b,c y,z組成的字串s 兩組case之間由空行隔開 該空行不用處理 字串長度len 1...
Manacher 馬拉車演算法
給定乙個字串,求出其的最長回文子串 乙個將時間複雜度優化到o n 的演算法 暴力演算法,但不是純暴力,即按照做過的事情不再去做來優化 我們知道,乙個回文串要麼是奇數的串 aba 要麼是偶數的串 abba 可以看出,乙個回文串有乙個對稱軸 對於奇數串aba來說,對稱軸就是b 而對於偶數串abba來說,...