Manacher算法

問題

求字符串的最長回文子串

例如:"aabbccbb"的最長回文子串是"bbccdd"

大家可能有各種思路去求解這個問題或辖,今天介紹一個比較快的的算法——Manacher算法

算法簡介

點(diǎn)擊這里

算法分析

以"aabbccbb"為列卤唉,介紹一下Manacher算法是如何工作的。

算法的大致思路就是根據(jù)回文對稱的特點(diǎn)威恼,遍歷字符串并以每個字符為中心向兩邊查找,并記錄回文的半徑長度绵载,按照正常的思路饲梭,會出現(xiàn)兩種情況偶回文和奇回文,例如"bbccbb"就是個偶回文早歇,比較難處理倾芝。

所以這個叫Manacher的人想了一種辦法,對字符串做以下處理

image

P數(shù)組就是記錄回文子串的半徑長度

這樣就解決了偶回文和奇回文的問題

接下來就是重頭戲缺前,算法的魅力也就在此蛀醉,Manacher算法充分利用回文的特點(diǎn),它定義了兩個變量:mx和id:

                id:是已知的最長回文子串的中心坐標(biāo)

                mx:以id為中心的最長回文子串的右邊界

這兩個變量干嘛用呢衅码,看圖:

image

如圖所示拯刁,n是i關(guān)于id對稱的對稱點(diǎn),因?yàn)橹皩匚膎的半徑長度有了計算逝段,我們可以借助這個已知信息減少我們的計算量垛玻,根據(jù)回文的特點(diǎn)割捅,可以得出P[i]=P[n],當(dāng)然這是個特殊情況帚桩,因?yàn)榛匚膎在回文id的邊界內(nèi)

當(dāng)回文n的左邊界超過mx'時候亿驾,即n-p[n]<mx',我們依然可以利用回文n的半徑信息账嚎,因?yàn)榛匚膎在回文id邊界內(nèi)的部分依然是回文(還是回文的特點(diǎn))莫瞬,此時的P[n]=n-mx',即P[n]=mx-i

所以P[i]=Min(P[n],mx-i);

代碼實(shí)現(xiàn)


public class Manacher {

    private String sourStr;
    private StringBuilder destStr;
    private int[] p;

    public Manacher(String sour){
        this.sourStr=sour;
        this.destStr=new StringBuilder();
        initStr();
    }

    private void initStr(){
        int len=0;
        destStr.append('#');
        for (int i=0;i<sourStr.length();i++){
            destStr.append(sourStr.charAt(i));
            destStr.append('#');
        }
        len=destStr.length();
        p=new int[len];
    }

    public String method(){
        int len=destStr.length();
        int mx=0;
        int id=1;
        int maxLen=-1;
        int result=-1;
        for (int i=1;i<len;i++){
            if(i<mx) p[i]=Math.min(p[2*id-i],mx-i);
            else p[i]=1;
            while (((i-p[i]>=0 && i+p[i]<len)) && destStr.charAt(i-p[i])==destStr.charAt(i+p[i]))
                p[i]++;
            if(mx<i+p[i]){
                id=i;
                mx=i+p[i];
            }
            if(maxLen<p[i]) {
                maxLen= p[i];
                result= i;
            }
        }
        return destStr.substring(result-maxLen+1,result+maxLen);
      }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末郭蕉,一起剝皮案震驚了整個濱河市疼邀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌召锈,老刑警劉巖旁振,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涨岁,居然都是意外死亡拐袜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門梢薪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹬铺,“玉大人,你說我怎么就攤上這事秉撇〈运” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵畜疾,是天一觀的道長赴邻。 經(jīng)常有香客問我,道長啡捶,這世上最難降的妖魔是什么姥敛? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮瞎暑,結(jié)果婚禮上彤敛,老公的妹妹穿的比我還像新娘。我一直安慰自己了赌,他們只是感情好墨榄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勿她,像睡著了一般袄秩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天之剧,我揣著相機(jī)與錄音郭卫,去河邊找鬼。 笑死背稼,一個胖子當(dāng)著我的面吹牛贰军,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蟹肘,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼词疼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了帘腹?” 一聲冷哼從身側(cè)響起寒跳,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎竹椒,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體米辐,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胸完,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了翘贮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赊窥。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狸页,靈堂內(nèi)的尸體忽然破棺而出锨能,到底是詐尸還是另有隱情,我是刑警寧澤芍耘,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布址遇,位于F島的核電站,受9級特大地震影響斋竞,放射性物質(zhì)發(fā)生泄漏倔约。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一坝初、第九天 我趴在偏房一處隱蔽的房頂上張望浸剩。 院中可真熱鬧,春花似錦鳄袍、人聲如沸绢要。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽重罪。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛆封,已是汗流浹背唇礁。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惨篱,地道東北人盏筐。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像砸讳,于是被迫代替她去往敵國和親琢融。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

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