5. 最长回文子串
难度中等3546收藏分享切换为英文接收动态反馈
给你一个字符串 s
,找到 s
中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
示例 3:
输入:s = "a"
输出:"a"
示例 4:
输入:s = "ac"
输出:"a"
提示:
1 <= s.length <= 1000
-
s
仅由数字和英文字母(大写和/或小写)组成
通过次数557,383
提交次数1,640,287
暴力法
动态规划
s[i,j]的长度为j-i+1
左闭右闭([])的数组长度为j-i+1,左闭右开([)])的数组长度为j-i+1
当j-i+1小于等于2时候 如果 如果s[i]==s[j] 则dp[i][j] = true 否则,为false
如果s[i,j]的长度(j-i+1)>2 时候
动态规划code:
public String longestPalindrome(String s) {
if (s == null) return null;
char[] cs = s.toCharArray();
if (cs.length <= 1) return s;
// 最长回文子串的长度(至少是1)
int maxLen = 1;
// 最长回文子串的开始索引
int begin = 0;
boolean[][] dp = new boolean[cs.length][cs.length];
// 从下到上(i由大到小)
for (int i = cs.length - 1; i >= 0; i--) {
// 从左到右(j由小到大)
for (int j = i; j < cs.length; j++) {
// cs[i, j]的长度
int len = j - i + 1;
dp[i][j] = (cs[i] == cs[j]) && (len <= 2 || dp[i + 1][j - 1]);
if (dp[i][j] && len > maxLen) { // 说明cs[i, j]是回文子串
maxLen = len;
begin = i;
}
}
}
return new String(cs, begin, maxLen);
}
以字符为中心向左右扩展
public String longestPalindromeEx(String s) {
if (s == null) return null;
char[] cs = s.toCharArray();
if (cs.length <= 1) return s;
// 最长回文子串的长度(至少是1)
int maxLen = 1;
// 最长回文子串的开始索引
int begin = 0;
for (int i = cs.length - 2; i >= 1; i--) {
// 以字符为中心向左右扩展
int len1 = palindromeLength(cs, i - 1, i + 1);
// 以字符右边的间隙为中心向左右扩展
int len2 = palindromeLength(cs, i, i + 1);
len1 = Math.max(len1, len2);
if (len1 > maxLen) {
maxLen = len1;
begin = i - ((maxLen - 1) >> 1);
}
}
// 以0号字符右边的间隙为中心的最长回文子串长度是2
if (cs[0] == cs[1] && maxLen < 2) {
// cs[0, 1]就是最长的回文子串
begin = 0;
maxLen = 2;
}
return new String(cs, begin, maxLen);
}
/**
* @return 从l开始向左、从r开始向右扫描,获得的最长回文子串的长度
*/
private int palindromeLength(char[] cs, int l, int r) {
while (l >= 0 && r < cs.length && cs[l] == cs[r]) {
l--;
r++;
}
return r - l - 1;
}
扩展2
public static String longestPalindromeEx2(String s) {
if (s == null) return null;
char[] cs = s.toCharArray();
if (cs.length <= 1) return s;
// 最长回文子串的长度(至少是1)
int maxLen = 1;
// 最长回文子串的开始索引
int begin = 0;
int i = 0;
while (i < cs.length) {
int l = i - 1;
// 找到右边第一个不等于cs[i]的位置
int r = i;
while (++r < cs.length && cs[r] == cs[i]);
// r会成为新的i
i = r;
// 从l向左,从r向右扩展
while (l >= 0 && r < cs.length && cs[l] == cs[r]) {
l--;
r++;
}
// 扩展结束后,cs[l + 1, r)就是刚才找到的最大回文子串
// ++l后,l就是刚才找到的最大回文子串的开始索引
int len = r - ++l;
if (len > maxLen) {
maxLen = len;
begin = l;
}
}
return new String(cs, begin, maxLen);
}
马拉车(Manacher)算法
留空位,彻底学习一下Manacher算法!