题目
5. Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
Example 1:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd"
Output: "bb"
分析
思路一:动态规划
定义状态:
dp[i][j]:从index=i到index=j(包括i,j)的一段子串是否是回文串;
dp[i][j] = true:是回文串;
dp[i][j] = false:不是回文串。
定义转移方程:
dp[i][j] = (s[i] == s[j] && dp[i+1][j-1]) (条件:i+1 <= j-1)
dp[i][j] = s[i] == s[j] (条件:i+1 > j-1)
定义初始值:
dp[s.length()-1][s.length()-1] = true;
思路二:(从中央位置开始)双向扩展扫描
对于串s的长度,分为奇数与偶数两种情况来考虑:
奇数情况下,中心位置是一个字符;
偶数情况下,中心位置是两个字符之间的间隙。
实现思路:从头开始遍历字符串s的每个字符,找到所有可作中心点的位置,对每个位置进行一次“双向扩展扫描”,找到以该位置为中心的最长回文子串。
题解
思路一Java实现
public class Solution {
public String longestPalindrome(String s) {
int length = s.length();
//处理字符串为空的特殊情况
if(length<1)return "";
//存储最长的回文子串的起始结束位置(两端包含)
int maxBegin = 0;
int maxEnd = 0;
//要返回的最长子串
String longestPalindrome = "";
boolean dp[][] = new boolean[length+1][length];
//设置初始值
dp[length-1][length-1] = true;
for(int begin=length-1;begin>=0;begin--){
for(int end=length-1;end>=begin;end--){
//转移方程
if(s.charAt(begin)==s.charAt(end)){
if(end-1<=begin+1 || dp[begin+1][end-1]){
dp[begin][end] = true;
//System.out.println("dp[" + i + "][" + j + "] = true");
//与目前已经记录下来的最长子串作对比(取相对更长的那一个)
if(end-begin>maxEnd-maxBegin){
maxBegin = begin;
maxEnd = end;
}
continue;
}
dp[begin][end] = false;
//System.out.println("dp[" + i + "][" + j + "] = false");
}
}
}
return s.substring(maxBegin,maxEnd+1);
}
// public static void main(String[] args) {
// System.out.println(new Solution().longestPalindrome("cbbd"));
// }
}
思路二Java实现
public class Solution2 {
public String longestPalindrome(String s) {
String longestPalindrome = "";
for (int i = 0; i < s.length(); i++) {
//奇数情况
int pre = i;
int next = i;
String s1 = getLongestPalindromeByIndex(pre, next, s);
//偶数情况
next++;
String s2 = getLongestPalindromeByIndex(pre, next, s);
s1 = s1.length() > s2.length() ? s1 : s2;
longestPalindrome = longestPalindrome.length() >= s1.length() ? longestPalindrome : s1;
}
return longestPalindrome;
}
public static String getLongestPalindromeByIndex(int pre, int next, String s) {
while (pre >= 0 && next < s.length() && s.charAt(pre) == s.charAt(next)) {
pre--;
next++;
}
//当退出循环时,说明当前pre和next不相等,从pre+1截取到next-1
return s.substring(pre + 1, next);
}
}