给定一个字符串 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) {
if(s.length() < 1){
return s;
}
int len = s.length(), startIndex=0, endIndex=startIndex;
String result = s.substring(0,1);
while (startIndex<len && (len-startIndex)>result.length()){
char target = s.charAt(startIndex);
int end = s.indexOf(target, endIndex+1);
if(end == -1) {
startIndex++;
endIndex = startIndex;
}else {
if(isPalindrome(s, startIndex, end)){
String tempStr = s.substring(startIndex, end+1);
if(result.length() < tempStr.length()){
result = tempStr;
}
}
endIndex = end;
}
}
return result;
}
public boolean isPalindrome(String s, int start, int end){
if(start<0 || end>=s.length()){
return false;
}
int startIndex = start, endIndex = end;
int len = end-start+1;
if(len%2 != 0){
endIndex=startIndex=start+len/2;
}else {
endIndex = start+len/2-1;
startIndex = endIndex+1;
}
String str1 = s.substring(start, endIndex+1);
String str2 = s.substring(startIndex, end+1);
return str1.equals(new StringBuilder(str2).reverse().toString());
}
}
方法二:动态规划
String longestPalindrome(String s) {
int len = s.length();
if (len == 0)
return s;
char[] aArray = s.toCharArray();
boolean[][] dp = new boolean[len][len];
int start = 0, end = 0;
for (int i = 0; i <len; i++)
dp[i][i] = true;
for (int r = 1; r < len; r++)
for (int l = 0; l < r; l++)
if (aArray[r]==aArray[l] && (r-l==1 || dp[l+1][r-1])) {
dp[l][r] = true;
if (r-l > end-start) {
start = l; end = r;
}
continue;
}else
dp[l][r] = false;
return s.substring(start, end+1);
}
方法三:借助动态规划的思想,找诸如“bab”、“aa”,再往两边扩展(好像由于代码过于冗余,时间优化并不是很明显)
public String longestPalindrome(String s) {
if(s.length() <1){
return s;
}
char[] cArray = s.toCharArray();
int len = s.length(), startIndex=0, endIndex=startIndex;
int leftIndex=startIndex, rightIndex=endIndex;
String result = s.substring(0,1);
int twiceFlag = 1;
while (startIndex<len-1){
if(startIndex>0 && twiceFlag==1){
if(cArray[startIndex-1] == cArray[startIndex+1]){
leftIndex = startIndex-1;
rightIndex = startIndex+1;
}
else{
twiceFlag = 2;
}
}else {
twiceFlag = 2;
}
if(twiceFlag==2 && cArray[startIndex] == cArray[startIndex+1]){
leftIndex = startIndex;
rightIndex = startIndex + 1;
} else if(twiceFlag!=1){
if(startIndex+2>=len){
break;
}else {
startIndex++;
twiceFlag=1;
continue;
}
}
boolean noJudgeLengthFlag = false;
while (leftIndex>=0&&rightIndex<len){
if(cArray[leftIndex] != cArray[rightIndex]){
break;
}else {
String tempStr = s.substring(leftIndex, rightIndex+1);
if(noJudgeLengthFlag || result.length()<tempStr.length()){
result = tempStr;
noJudgeLengthFlag = true;
}
}
rightIndex++;
leftIndex--;
}
if(twiceFlag == 1){
twiceFlag = 2;
}else {
startIndex++;
twiceFlag = 1;
}
}
return result;
}
方法三(优化后,中心扩展算法)整体思路是一致的,代码精简
class Solution {
public String longestPalindrome(String s) {
if(null ==s || s.length() < 1){
return s;
}
char[] cArray = s.toCharArray();
int startIndex=0, endIndex=startIndex;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(cArray, i, i);
int len2 = expandAroundCenter(cArray, i, i + 1);
int maxLen = Math.max(len1, len2);
if(maxLen>endIndex-startIndex+1){
startIndex = i- (maxLen-1)/2;
endIndex = i + maxLen/2;
}
}
return s.substring(startIndex, endIndex+1);
}
int expandAroundCenter(char[] s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length && s[L] == s[R]) {
L--;
R++;
}
return R - L - 1;
}
}
方法四:Manacher’s Algorithm