import java.util.*; /** * NC17 最长回文子串 * @author d3y1 */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param A string字符串 * @return int整型 */ public int getLongestPalindrome (String A) { // return solution1(A); // return solution2(A); // return solution3(A); return solution4(A); } /** * 滑动窗口 * @param A * @return */ private int solution1(String A){ int len = A.length(); for(int gap = len; gap > 0; gap--){ for(int i = 0; i+gap <= len; i++){ if(isPalindrome(A.substring(i, i+gap))){ return gap; } } } return 0; } /** * 是否回文串 * @param sub * @return */ private boolean isPalindrome(String sub){ for(int i=0,j=sub.length()-1; i<j; i++,j--){ if(sub.charAt(i) != sub.charAt(j)){ return false; } } return true; } /** * 是否回文串 * @param sub * @return */ private boolean checkPalindrome(String sub){ return sub.equals(new StringBuffer(sub).reverse().toString()); } /** * 动态规划 * * dp[i][j]表示子串[i,j](下标从0开始)是否为回文串(dp[i][j]=0: 非回文串 , dp[i][j]>0: 为回文串) * * { = 0, 子串[i,j]非回文串 * dp[i][j] { * { > 0, 子串[i,j]为回文串 且长度为该值 * @param A * @return */ private int solution2(String A){ char[] chars = A.toCharArray(); int len = chars.length; int result = 1; int[][] dp = new int[len][len]; for(int i = 0; i < len; i++){ dp[i][i] = 1; } for(int i = 0; i+1 < len; i++){ if(chars[i] == chars[i+1]){ dp[i][i+1] = 2; result = 2; } } for(int gap = 2; gap < len; gap++){ for(int i = 0; i+gap < len; i++){ // 左右两边字符相同 且 之间子串为回文串 if(chars[i]==chars[i+gap] && dp[i+1][i+gap-1]>0){ // 回文串 长度+2 dp[i][i+gap] = dp[i+1][i+gap-1] + 2; }else{ // 非回文串 dp[i][i+gap] = 0; } result = Math.max(result, dp[i][i+gap]); } } return result; } /** * 贪心: 中心扩展法 * @param A * @return */ private int solution3(String A){ int result = 1; for(int i = 0; i+1 < A.length(); i++){ result = Math.max(result, Math.max(spread(A,i,i), spread(A,i,i+1))); } return result; } /** * 中心扩展法: 分别向左右两边扩展 * @param A * @param left * @param right * @return */ private int spread(String A, int left, int right){ while(0<=left && right<A.length() && A.charAt(left)==A.charAt(right)){ left--; right++; } return right-left-1; } /** * Manacher算法 * @return */ private int solution4(String A){ char[] mChars = manacher(A); int mCharsLen = mChars.length; // 回文半径 int[] pRadius = new int[mCharsLen]; int index = -1; // 之前已经遍历字符各回文半径最右侧再往右一位 -> 最右即将到达的位置 int pRight = -1; int max = 1; for(int i = 0; i < mCharsLen; i++){ pRadius[i] = pRight>i ? Math.min(pRadius[2*index-i], pRight-i) : 1; while(0<=i-pRadius[i] && i+pRadius[i]<mCharsLen){ if(mChars[i-pRadius[i]] == mChars[i+pRadius[i]]){ pRadius[i]++; }else{ break; } } // pRight if(i+pRadius[i] > pRight){ pRight = i+pRadius[i]; index = i; } // 回文串长度 pRadius[i]-1 max = Math.max(max, pRadius[i]-1); } return max; } /** * 字符串初始化处理: 奇回文串 和 偶回文串 方便统一处理 * * bcbaa -> #b#c#b#a#a# * ba -> #b#a# * * @param str * @return */ private char[] manacher(String str){ char[] chars = str.toCharArray(); char[] result = new char[str.length()*2+1]; int index = 0; for(int i = 0; i < result.length; i++){ result[i] = (i&1)==0 ? '#' : chars[index++]; } return result; } }