Manacher算法「最長回文字符串」

Manacher算法原理

  • 最長回文字符串包括奇數(shù)長的和偶數(shù)長的,求的時(shí)候都要分情討論,Manacher算法做了一個(gè)簡單的處理爷狈,很巧妙地把奇數(shù)長度回文串與偶數(shù)長度回文串統(tǒng)一考慮侍芝,也就是在每個(gè)相鄰的字符之間插入一個(gè)分隔符,串的首尾也要加,當(dāng)然這個(gè)分隔符不能再原串中出現(xiàn)宪萄,一般可以用‘#’字符。
    這樣一來榨惰,原來的奇數(shù)長度回文串還是奇數(shù)長度拜英,偶數(shù)長度的也變成以‘#’為中心奇數(shù)回文串了。
    其次給每個(gè)字符串首部加一個(gè)題目中不會(huì)出現(xiàn)的字符读串,避免處理越界問題聊记。(一般加’$’)


    如圖字符串S就是通過Manacher算法預(yù)處理得到的新串
    P數(shù)組記錄的以 S[i]為中間S字符的回文串向右能匹配的最大長度(包括S[i]這個(gè)字符).
    當(dāng)S[i]不是所加字符‘#’時(shí),P[i]-1就是字符串長度了

  • 假設(shè)以i為中心的回文串長度為len,因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=p%5B%20i" alt="p[ i" mathimg="1">]記錄以 S[i]為中間字符的回文串向右能匹配的長度恢暖,所以有
    len=2*p[ i ]-1;
    又因?yàn)榇藭r(shí)串中加了其他字符#排监,以s[i]為中心的回文串一定是以#開頭和結(jié)尾的,以#為中間字符的就是長度為偶數(shù)的杰捂,以非#號(hào)為中間字符的就是長度為奇數(shù)的舆床,例如“#b#b#”“#b#a#b#”所以減去最前或者最后的‘#’字符就是原串中長度的2倍,即原串長度為(S-1)/2嫁佳,化簡的P[i]-1挨队。

Manacher算法實(shí)現(xiàn)

  • Manacher算法實(shí)現(xiàn)就是要找出p數(shù)組,如何找出P數(shù)組是關(guān)鍵.

首先從左往右依次計(jì)算P[i],當(dāng)計(jì)算P[i]時(shí)蒿往,P[j](0<=j<i)已經(jīng)計(jì)算完畢盛垦。設(shè)mx為之前計(jì)算中最長回文子串的右端點(diǎn)的最大值,并且設(shè)取得這個(gè)最大值的位置為id瓤漏,分兩種情況:

情況1:

  1. i<=mx
    那么找到i相對(duì)于id的對(duì)稱位置腾夯,設(shè)為j,那么如果p[j]<mx-i
    因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=i%2Bj%3D2*id" alt="i+j=2*id" mathimg="1">,j能向左匹配的最左端點(diǎn)的坐標(biāo)是j-p[j]+1
    所以可知p[j]+2*id<mx+j,所以可知2*id-mx<j-p[j]+1
    向如下圖:

    那么說明以j為中心的回文串一定在以id為中心的回文串的內(nèi)部蔬充,且ji關(guān)于位置id對(duì)稱,那么意味著以S[i]為中間字符的回文串能向右匹配最右端點(diǎn)沒有超過mx蝶俱。由回文串的定義可知,一個(gè)回文串反過來還是一個(gè)回文串饥漫,所以以i為中心的回文串的長度至少和以j為中心的回文串一樣榨呆,所以P[i]=P[j]
  2. 如果P[j]>=mx-i,由對(duì)稱性庸队,說明以i為中心的回文串可能會(huì)延伸到mx之外积蜻,而大于mx的部分我們還沒有進(jìn)行匹配,所以要從mx+1位置開始一個(gè)一個(gè)進(jìn)行匹配彻消,直到發(fā)生失配浅侨,從而更新mx和對(duì)應(yīng)的id以及P[i]

    雖然p[j]>mx-i,但是可以保證的是i<->mx這一段是跟2*id-mx<->j是一樣的证膨,說明以s[i]為中心的回文串至少有mx-i這么長

情況2:
i>mx
如果i比mx還要大,說明對(duì)于中點(diǎn)為i的回文串還一點(diǎn)都沒有匹配鼓黔,這個(gè)時(shí)候央勒,就只能老老實(shí)實(shí)地一個(gè)一個(gè)匹配了不见,匹配完成后要更新mx的位置和對(duì)應(yīng)的id以及P[i]


        int len=strlen(s);
        int mx=0;
        int id=0;
        int res=-1;
        for(int i=len;i>=0;i--)
        {
            s[i*2+2]=s[i];
            s[i*2+1]='#';
        }
        s[0]='$';//加上特殊字符防止越界
        for(int i=0;i<=2*len+1;i++)
        {
            if(mx>i)//mx<i的情況
            {
                p[i]=min(p[2*id-i],mx-i);//比較p[j]大還是mx-i大崔步,取小的
            }
            else//如果i>=mx稳吮,要從頭開始匹配
            {
                p[i]=1;
            }
            while(s[i-p[i]]==s[i+p[i]])//一個(gè)一個(gè)比較
            {
                p[i]++;
            }
            if(p[i]+i>mx))//若新計(jì)算的回文串右端點(diǎn)位置大于mx,要更新id和mx的值

            {
                mx=p[i]+i;
                id=i;
            }
            res=max(res,p[i]-1);
        }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末井濒,一起剝皮案震驚了整個(gè)濱河市灶似,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑞你,老刑警劉巖酪惭,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異者甲,居然都是意外死亡春感,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門虏缸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲫懒,“玉大人,你說我怎么就攤上這事裆站≡炅樱” “怎么了俱萍?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長颂翼。 經(jīng)常有香客問我,道長撵溃,這世上最難降的妖魔是什么疚鲤? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮缘挑,結(jié)果婚禮上集歇,老公的妹妹穿的比我還像新娘。我一直安慰自己语淘,他們只是感情好诲宇,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惶翻,像睡著了一般姑蓝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吕粗,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天纺荧,我揣著相機(jī)與錄音,去河邊找鬼。 笑死宙暇,一個(gè)胖子當(dāng)著我的面吹牛输枯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播占贫,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼桃熄,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了型奥?” 一聲冷哼從身側(cè)響起瞳收,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厢汹,沒想到半個(gè)月后螟深,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坑匠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年血崭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厘灼。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夹纫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出设凹,到底是詐尸還是另有隱情舰讹,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布闪朱,位于F島的核電站月匣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏奋姿。R本人自食惡果不足惜锄开,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望称诗。 院中可真熱鬧萍悴,春花似錦、人聲如沸寓免。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽袜香。三九已至撕予,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蜈首,已是汗流浹背实抡。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工欠母, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人澜术。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓艺蝴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸟废。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容