最大回文子串
阿新 • • 發佈:2019-01-02
5. 最長迴文子串
給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。
示例 1:
輸入: "babad" 輸出: "bab" 注意: "aba"也是一個有效答案。
示例 2:
輸入: "cbbd" 輸出: "bb"
Manacher演算法
class Solution { public static String longestPalindrome(String s) { if(s == null || s.length() < 1) return ""; String str = dealWithS(s); // 處理一下s,即將給字串s的中間加上特殊字元,這樣無論對於奇數字符還是偶數字符可以做同樣的處理 int[] res = new int[str.length()]; int R = 0; // 當前所能擴充套件的半徑 int C = 0; // C位置的半徑為R int maxC= 0; // 最長的半徑的位置 res[0] = 0; for(int i = 1; i < str.length(); i++) { int j = 2 * C - i; // i點的對稱點 if(j >= 0 && res[j] < R - i) // 對稱點存在且對稱點的迴文半徑在C的迴文中 { res[i] = res[j]; } else // 否則,需要根據i點一點一點的計算 { int k = 1; while(R + k < str.length() && 2 * i - R - k >= 0) { if(str.charAt(R + k) == str.charAt(2 * i - R - k)) k ++; else break; } res[i] = R -i + k - 1; if(res[i] + i > R) { R = res[i] + i; C = i; } } maxC = res[maxC] > res[i] ? maxC : i; // maxC儲存的是迴文半徑最大的那個點的位置 } String subStr = str.substring(maxC - res[maxC], maxC + res[maxC] + 1); StringBuffer sb = new StringBuffer(); for(int i = 0; i < subStr.length(); i++) { if(subStr.charAt(i) != '#') sb.append(subStr.charAt(i)); } return sb.toString(); } public static String dealWithS(String s) // 將原字串進行處理 { StringBuffer sb = new StringBuffer(); sb.append("#"); for(int i = 0; i < s.length (); i++) { sb.append(s.charAt(i)); sb.append("#"); } return sb.toString(); } }
方法二:
class Solution { public String longestPalindrome(String s) { if(s.length()<=1) return s; char[] characters = s.toCharArray(); //用於存放str中最長迴文子串所對應的下標 int[] range = {0,1}; for(int i = 0;i<characters.length;i++){ i = helper(i,characters,range); } return s.substring(range[0],range[1]); } private int helper(int index,char[] c,int[] range) { int low = index; int high = index; //如果遇到相同字元,則high進位,如abba ,這樣偶迴文子串也可以當做奇迴文處理了 while(high<c.length-1 && c[high]==c[high+1]){ high++; } int cursor = high; while(high+1<c.length&&low-1>=0&&c[low-1]==c[high+1]){ low--; high++; } if(high-low+1>range[1]-range[0]){ range[0] = low; range[1] = high + 1; } return cursor; } }