题目:5. 最长回文子串 给你一个字符串 s
,找到 s
中最长的回文子串。
难度:中等
示例 1:
输入:s = “babad” 输出:”bab” 解释:”aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd” 输出:”bb”
示例 3:
输入:s = “a” 输出:”a”
示例 4:
输入:s = “ac” 输出:”a”
提示:
1 <= s.length <= 1000
s
仅由数字和英文字母(大写和/或小写)组成
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
暴力解法
动态规划
中心扩展算法
Manacher算法
官方解题代码 暴力解法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution { public String longestPalindrome (String s) { int len = s.length(); if (len < 2 ){ return s; } char [] c = s.toCharArray(); int begin = 0 , maxlen = 1 ; for (int i = 0 ; i < len - 1 ; i++){ for (int j = i + 1 ; j < len; j++){ if (j - i + 1 > maxlen && validPalindromic(c, i, j)){ begin = i; maxlen = j - i + 1 ; } } } return s.substring(begin, begin + maxlen); } public boolean validPalindromic (char [] c, int left, int right) { while (left < right){ if (c[left] != c[right]){ return false ; } left++; right--; } return true ; } }
动态规划 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 public class Solution { public String longestPalindrome (String s) { int len = s.length(); if (len < 2 ) { return s; } int maxLen = 1 ; int begin = 0 ; boolean [][] dp = new boolean [len][len]; for (int i = 0 ; i < len; i++) { dp[i][i] = true ; } char [] charArray = s.toCharArray(); for (int L = 2 ; L <= len; L++) { for (int i = 0 ; i < len; i++) { int j = L + i - 1 ; if (j >= len) { break ; } if (charArray[i] != charArray[j]) { dp[i][j] = false ; } else { if (j - i < 3 ) { dp[i][j] = true ; } else { dp[i][j] = dp[i + 1 ][j - 1 ]; } } if (dp[i][j] && j - i + 1 > maxLen) { maxLen = j - i + 1 ; begin = i; } } } return s.substring(begin, begin + maxLen); } }
中心扩展算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution { public String longestPalindrome (String s) { int len = s.length(); if (len < 2 ){ return s; } char [] c = s.toCharArray(); int begin = 0 , maxlen = 1 ; for (int i = 0 ; i < len - 1 ; i++){ int oddLen = expandAroundCenter(c, i, i); int evenLen = expandAroundCenter(c, i, i + 1 ); int curMaxLen = Math.max(oddLen, evenLen); if (curMaxLen > maxlen){ maxlen = curMaxLen; begin = i - (maxlen - 1 ) / 2 ; } } return s.substring(begin, begin + maxlen); } public int expandAroundCenter (char [] c, int left, int right) { while (left >= 0 && right < c.length){ if (c[left] != c[right]){ break ; } left--; right++; } return right - left - 1 ; } }
Manacher算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Solution { public String longestPalindrome (String s) { int start = 0 , end = -1 ; StringBuffer t = new StringBuffer ("#" ); for (int i = 0 ; i < s.length(); ++i) { t.append(s.charAt(i)); t.append('#' ); } t.append('#' ); s = t.toString(); List<Integer> arm_len = new ArrayList <Integer>(); int right = -1 , j = -1 ; for (int i = 0 ; i < s.length(); ++i) { int cur_arm_len; if (right >= i) { int i_sym = j * 2 - i; int min_arm_len = Math.min(arm_len.get(i_sym), right - i); cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len); } else { cur_arm_len = expand(s, i, i); } arm_len.add(cur_arm_len); if (i + cur_arm_len > right) { j = i; right = i + cur_arm_len; } if (cur_arm_len * 2 + 1 > end - start) { start = i - cur_arm_len; end = i + cur_arm_len; } } StringBuffer ans = new StringBuffer (); for (int i = start; i <= end; ++i) { if (s.charAt(i) != '#' ) { ans.append(s.charAt(i)); } } return ans.toString(); } public int expand (String s, int left, int right) { while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { --left; ++right; } return (right - left - 2 ) / 2 ; } }