最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。 示例 2:
输入:s = "cbbd" 输出:"bb"
提示:
1 <= s.length <= 1000 s 仅由数字和英文字母组成
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
};
-
方法一(暴力解法):
-
方法二(中心扩散):
function longestPalindrome(s: string): string { let Resleft = 0; let Resright = 0; let maxLen = 0; let i = 0; //设i为中心的索引 while(i < s.length) { let left = i - 1; while (left >= 0 && s[i] === s[left]) { left--; } let right = i + 1; while (right < s.length && s[i] === s[right]) { right++; } const end = right; //这里的right是右边第一个跟中心s[i]不相等的字符索引,保存下来,等会i直接跳到end处,可减少重复中心的计算 while (left >= 0 && right < s.length && s[left] === s[right]) { left--; right++; } if (maxLen < right - left - 1) { maxLen = right - left - 1; Resleft = left + 1; Resright = right - 1; } i = end; } return s.substring(Resleft, Resright + 1); }; -
方法三(动态规划):
var longestPalindrome = function(s) { let len = s.length let maxLen = 1 let start = 0 let dp = Array.from(new Array(len), ()=> new Array(len).fill(false)) for(let l = 2 ; l <= len ; l ++){ // 字串的长度,字符串长度从 2 开始 for(let i = 0 ; i < len ; i ++){ // i 起始的位置 // j 为终止位置 let j = i + l - 1 // 初始条件 if((l == 2 || l == 3) && s[i] == s[j]){ dp[i][j] = true } // 递推公式 if(s[i] === s[j] && dp[i + 1][j - 1] == true){ dp[i][j] = true } if(dp[i][j] && l > maxLen){ maxLen = l; start = i } } } return s.substr(start , maxLen) }; -
方法四(Manacher 算法):
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; } }