Manacher算法的詳細講解

Manacher算法昭娩,又叫“馬拉車”算法,可以在時間復(fù)雜度為O(n)的情況下求解一個字符串的最長回文子串長度的問題。

一浦楣、回文子串的一般解法

比較簡單的思路是將字符串的每一個字符作為回文子串的中心對稱點踱蠢,每次保存前面求得的回文子串的最大值火欧,最后得到的就是最長的回文子串的長度棋电,這種方式的時間復(fù)雜度是O(n^2)。在求解過程中苇侵,基數(shù)的回文子串與偶數(shù)的回文子串是不一樣的赶盔。比如最長回文子串為aba,對稱中心就是b榆浓,如果最長回文子串為abba于未,則對稱中心應(yīng)該為兩個b之間,為了解決這個問題陡鹃,可以在每個字符兩邊加上一個符號烘浦,具體什么符號(是字符串里面的符號也行)對結(jié)果沒有影響,比如加上“#”萍鲸,則上述的兩個序列變成了#a#b#a#和#a#b#b#a#闷叉,求出的長度分別為6和9,再除以2就可以得到最后的結(jié)果3和4脊阴。這種方式的時間復(fù)雜度太高握侧,下面介紹時間復(fù)雜度為O(n)的Manacher算法。

二嘿期、Manacher算法中的基礎(chǔ)概念

在進行Manacher算法時藕咏,字符串都會進行上面的進入一個字符處理,比如輸入的字符為acbbcbds秽五,用“#”字符處理之后的新字符串就是#a#c#b#b#c#b#d#s#孽查。

1、回文半徑數(shù)組radius

回文半徑數(shù)組radius是用來記錄以每個位置的字符為回文中心求出的回文半徑長度坦喘,如下圖所示盲再,對于p1所指的位置radius[6]的回文半徑是5,每個位置的回文半徑組成的數(shù)組就是回文數(shù)組瓣铣,所以#a#c#b#b#c#b#d#s#的回文半徑數(shù)組為[1, 2, 1, 2, 1, 2, 5, 2, 1, 4, 1, 2, 1, 2, 1, 2, 1]答朋。

要處理的字符串

2秽梅、最右回文右邊界R

一個位置最右回文右邊界指的是這個位置及之前的位置的回文子串卿樱,所到達的最右邊的地方。比如對于字符串#a#c#b#b#c#b#d#s#医瘫,求它的每個位置的過程如下:

最右回文右邊界R過程

最開始的時候R=-1蓖救,到p=0的位置洪规,回文就是其本身,最右回文右邊界R=0;p=1時循捺,有回文串#a#斩例,R=2;p=2時从橘,R=2;P=3時念赶,R=6;p=4時础钠,最右回文右邊界還是p=3時的右邊界,R=6,依次類推叉谜。

3旗吁、最右回文右邊界的對稱中心C

就是上面提到的最右回文右邊界的中心點C,如下圖停局,p=4時阵漏,R=6,C=3

最右回文右邊界的對稱中心C

三翻具、Manacher算法的流程

首先大的方面分為兩種情況:

第一種情況:下一個要移動的位置在最右回文右邊界R的右邊履怯。

比如在最開始時,R=-1,p的下一個移動的位置為p=0裆泳,p=0在R=-1的右邊叹洲;p=0時,此時的R=0工禾,p的下一個移動位置為p=1运提,也在R=0的右邊。

在這種情況下闻葵,采用普遍的解法民泵,將移動的位置為對稱中心,向兩邊擴槽畔,同時更新回文半徑數(shù)組栈妆,最右回文右邊界R和最右回文右邊界的對稱中心C。

第二種情況:下一個要移動的位置就是最右回文右邊界R或是在R的左邊

在這種情況下又分為三種:

1厢钧、下一個要移動的位置p1不在最右回文右邊界R右邊鳞尔,且cL<pL。

p2是p1以C為對稱中心的對稱點早直;

pL是以p2為對稱中心的回文子串的左邊界;

cL是以C為對稱中心的回文子串的左邊界寥假。

這種情況下p1的回文半徑就是p2的回文半徑radius[p2]。

p1<=R且cL<pL

2霞扬、下一個要移動的位置票p1不在最右回文右邊界R的右邊糕韧,且cL>pL。

p2是p1以C為對稱中心的對稱點喻圃;

pL是以p2為對稱中心的回文子串的左邊界萤彩;

cL是以C為對稱中心的回文子串的左邊界。

這種情況下p1的回文半徑就是p1到R的距離R-p1+1级及。

p1<=R且cL>pL

3乒疏、下一個要移動的位置票p1不在最右回文右邊界R的右邊额衙,且cL=pL饮焦;

p2是p1以C為對稱中心的對稱點怕吴;

pL是以p2為對稱中心的回文子串的左邊界;

cL是以C為對稱中心的回文子串的左邊界县踢。

這種情況下p1的回文半徑就還要繼續(xù)往外擴转绷,但是只需要從R之后往外擴就可以了,擴了之后更新R和C硼啤。

p1<=R且cL==pL

四议经、Manacher時間復(fù)雜度分析

從上面的分析中,可以看出谴返,第二種情況的1煞肾,2的求某個位置的回文半徑的時間復(fù)雜度是O(1),對于第一種情況和第二種情況的3嗓袱,R是不斷的向外擴的籍救,不會往回退,而且尋找回文半徑時渠抹,R之內(nèi)的位置是不是進行判斷的蝙昙,所以對整個字符串而且,R的移動是從字符串的起點移動到終點梧却,時間復(fù)雜度是O(n),所以整個manacher的時間復(fù)雜度是O(n)奇颠。

五、Manacher的代碼實現(xiàn)

public static void main(String[] args) {
        String str = "abcdcbafabcdck";
        //String str = "acbbcbds";
        System.out.println(manacher(str));
    }

    public static char[] manacherString(String str){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            sb.append("#");
            sb.append(str.charAt(i));
        }
        sb.append("#");
        return sb.toString().toCharArray();
    }

    public static int manacher(String str){
        if(str == null || str.length() < 1){
            return 0;
        }
        char[] charArr = manacherString(str);
        int[] radius = new int[charArr.length];
        int R = -1;
        int c = -1;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < radius.length; i++) {
            radius[i] = R > i ? Math.min(radius[2*c-i],R-i+1):1;
            while(i+radius[i] < charArr.length && i - radius[i] > -1){
                if(charArr[i-radius[i]] == charArr[i+radius[i]]){
                    radius[i]++;
                }else{
                    break;
                }
            }
            if(i + radius[i] > R){
                R = i + radius[i]-1;
                c = i;
            }
            max = Math.max(max,radius[i]);
        } 
        return max-1;
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末放航,一起剝皮案震驚了整個濱河市烈拒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌广鳍,老刑警劉巖缺菌,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異搜锰,居然都是意外死亡伴郁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門蛋叼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來焊傅,“玉大人,你說我怎么就攤上這事狈涮『ィ” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵歌馍,是天一觀的道長握巢。 經(jīng)常有香客問我,道長松却,這世上最難降的妖魔是什么暴浦? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任溅话,我火速辦了婚禮,結(jié)果婚禮上歌焦,老公的妹妹穿的比我還像新娘飞几。我一直安慰自己,他們只是感情好独撇,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布屑墨。 她就那樣靜靜地躺著,像睡著了一般纷铣。 火紅的嫁衣襯著肌膚如雪卵史。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天搜立,我揣著相機與錄音程腹,去河邊找鬼。 笑死儒拂,一個胖子當(dāng)著我的面吹牛寸潦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播社痛,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼见转,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蒜哀?” 一聲冷哼從身側(cè)響起斩箫,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撵儿,沒想到半個月后乘客,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡淀歇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年易核,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浪默。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡牡直,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纳决,到底是詐尸還是另有隱情碰逸,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布阔加,位于F島的核電站饵史,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胳喷,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一湃番、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厌蔽,春花似錦牵辣、人聲如沸摔癣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽择浊。三九已至戴卜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間琢岩,已是汗流浹背投剥。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留担孔,地道東北人江锨。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像糕篇,于是被迫代替她去往敵國和親啄育。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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

  • 題目 有這么一個字符串s拌消,找到s中最長的回文子串挑豌,假設(shè)s的長度最大值是1000.所謂回文就是中心軸對稱的字符串。 ...
    Stroman閱讀 405評論 0 1
  • 三十歲的你铝阐,被家庭瑣事摧殘的你,被熊孩子折磨得死去活來的你铐拐,還記得十四歲那年讓你怦然心動的那個boy嗎饰迹? 1980...
    水清的minguo往事閱讀 1,020評論 4 4
  • 你永遠也想不到我了解你這么多,即使我只和你見過兩次面余舶,說過三句話啊鸭,看過一場電影。但是我知道你愛什么匿值,做過什...
    北彩閱讀 523評論 0 0
  • 選擇性放棄要比永久性痛苦更可貴赠制。 并不是所有的付出都會有回報。 有花無果,難得放空钟些。 做不到克制烟号,就選擇停止。 今...
    世俗凡人閱讀 213評論 2 1
  • 也許你的眼里政恍,從未看清過我的樣貌汪拥,但我相信,在你心里篙耗,應(yīng)如我信任你一般信任我迫筑。 也許你不能再和許多喜愛你的人見面,...
    Daisy2lan閱讀 165評論 0 0