给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { public String longestPalindrome(String s) { // Manacher 算法 // 1. 对原字符串添加分隔符,例如 "babad" 添加分隔符以后得到 "@#b#a#b#a#d#$" char[] A = new char[s.length() * 2 + 3]; A[0] = '@'; A[1] = '#'; int t = 2; for(char c: s.toCharArray()) { A[t++] = c; A[t++] = '#'; } A[t] = '$'; // 辅助数组Z,记录以当前字符为中心,能够扩散的步数,最大值为最长回文串长度 int[] Z = new int[A.length]; // right:记录当前向右扩展的最远边界, center:right 的回文中心的索引值 // idx: 最长回文串的中心 maxZ:Z值(长度) int right = 0, center = 0, idx = 0, maxZ = 0; for(int i = 1; i < A.length - 1; i++) { // mirror=2*center-i为i关于center镜像对称点,right-i为i向左走到center的距离 // 当Z[mirror]<=right-i时,i点处和镜像点有相同的对称性,Z[i]=Z[mirror] // 当Z[mirror]>right-i时,此时不能再扩散了,因为最大边界为right, // right+1处关于center镜像点字符一定不同,Z[i]=right-i if(right > i) { Z[i] = Math.min(Z[2 * center - i], right - i); } // 中心扩散法更新Z值 while(A[i - Z[i] - 1] == A[i + Z[i] + 1]) { Z[i]++; } // 记录最大Z值 if(Z[i] > maxZ) { maxZ = Z[i]; idx = i; } // 更新right和center if(i + Z[i] > right) { center = i; // i + Z[i] 就是right right = i + Z[i]; } } return s.substring((idx - maxZ) / 2 , (idx - maxZ) / 2 + maxZ); } }