字串處理系列 最長回文子串

2021-06-25 12:35:29 字數 1688 閱讀 5964

這是一道非常經典的字串處理問題,回文是指該字串是對稱的,如abcdcba, aabbaa

該問題最樸素的解法是找到所有子串,判斷是不是回文並找出最長的回文子串,**很簡單,這裡就不寫了;

第二種解法是中心點法,即以某個點為中心,用兩個索引分別往前和往後走,找出其回文,這裡需要注意回文是奇數個字元還是偶數個字元,即要處理兩種情況;

第三種解法是最有效的解法,時間複雜度比以上兩種方法都低o(n),該方法被稱為manacher演算法,下面介紹該演算法的思路:

首先該演算法採用了乙個非常巧妙的方式將所有字串的長度轉換成奇數,即通過在字串前面、字串後面及各個字元之間新增乙個特殊字元(如『#』,『$』),以字串abcdedcbf為例,處理後的字串s = "#a#b#b#d#e#d#b#b#f#";

然後,建立乙個輔助陣列p,p中元素p[i]儲存的是以s[i]為中心的回文半徑,如下所示:

s   #  a  #  b  #  b  #  d  #  e  #  d  #  b  #  b  #  f  #

p  1   2  1  2  3  2  1  2  1  8  1  2  1  2  3  2  1  2  1

這個演算法的關鍵點在於p[i]的計算,p[i]是通過兩個輔助變數id,mx來求解的,mx代表能到達最右邊的回文的結尾,id代表該回文的中心點;當mx > i 時,則p[i] = min;這樣可能比較難理解,我們用圖表示出這兩種情況會比較容易理解,看明白圖後就會發現很簡單:

2*id - i是i關於id的對稱點,由於mx > i,所以i到mx之間的字元,mx的對稱點到j之間的字元對稱,如果以s[j]為中心的回文還沒延伸到mx的對稱點,因為i和j對稱,所以以s[i]為中心的回文長度就等於p[j],即p[2*id-i];

當mx-i < p[j]時,此時我們可以先將p[i]指定為mx-i,然後再判斷s[mx]之後的字元是否與前面的字元對稱,該判斷過程與另一種情況相同,即mx <= i時,此時也需要乙個個字元判斷;

該演算法的**如下:

public string longestpalindrome(string s) 

string str = sb.tostring();

int p = new int[str.length()];

int id = -1;

int mx = 0;

int max = 0;

for(int i = 0; i < str.length(); i++)else

while(i+p[i] < str.length() && i-p[i] >= 0 && str.charat(i+p[i]) == str.charat(i-p[i]))

p[i]++;

if(i+p[i] > mx)

if(p[i] > p[max])

}stringbuilder result = new stringbuilder();

for(int i = max-p[max]+1; i <= max+p[max]-1; i++)

return result.tostring();

}

詳見leetcode:

字串處理 最長回文子串

題目描述 給定乙個字串,求它的最長回文子串的長度.方法一 中心擴充套件法.由於回文串中,以某個字元為中心的字首和字尾一定是相同字元。可以利用此方法列舉中心位置,然後進行擴充套件,從而找到最長回文子串。include include using namepace std int longestpali...

字串 最長回文子串

最長回文子串 回文子串 即正著看和倒著看相同的子串,如 abcba yyxyy。由於此類題目為面試筆試常考題目,所以現在就來整理一下啦。1 暴力求解法 最直接的想法就是暴力求解,但是我們可以看到下面的 時間複雜度是o n 3 string findlongeststring string str 暴...

字串 最長回文子串

介紹一下幾個概念 就是從左往右和從右往左讀是一樣的。就如標語 我為人人,人人為我 子串,顧名思義,就是在原字串中的子集,就叫子串。串就是不能分割的,就是連在一起,這個要區別與子串行,子串行就是一段 一段的。列舉各個起點和終點,然後進行判斷該子串是否為回文,最後就是更新最長的回文串。列舉起點和終點 o...