最长回文子串
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
思路:
为什么说这道题可以用动态规划呢?这道题是求最长回文子串,是求极值,那么这就可以用动态规划解题。想到动规,就要想到状态转移方程。这很重要。我们可以从最后一步往前推,得到最终结果的有2种情况:它的前一步是最长回文子串,一是加上最后一步是回文;二是加上最后一步不是回文。
推出:dp[i][j] = max( dp[i+1][j-1](最后一步不是回文), dp[i][j](最后一步是回文) ),i为字符串开始位置,j为字符串结束位置,dp为字符串长度。 具体实现如下
class Solution
{
public String longestPalindrome(String s)
{
if(s.length() < 1)
return "";
int start = 0, end = 0, max = 0;
for (int i = 0; i < s.length(); i++)
{
int lenA = midExtend(s,i,i); //如果s长度为偶数,i、i为中间向两边扩展的数
int lenB = midExtend(s,i,i+1); //s长度为奇数,i、i+1为中间向两边扩展的数
lenA = Math.max(lenA, lenB);
if(lenA > max) //找最大长度的回文字符串
{
max = lenA;
start = i-(max-1)/2;//回文字符串的开始位置
end = i + max/2; //回文字符串的结束位置
}
}
return s.substring(start,end+1);
}
private int midExtend(String s, int left, int right)
{
int l = left;
int r = right;
while(l>=0 && r < s.length())
{
//判断是否是回文字符串
if(s.charAt(l) != s.charAt(r))
break;
//是回文,则字符串向两边扩展1位,再判断是否是回文
l--;
r++;
}
return r-l-1; //回文字符串长度
}
}
常规思路(非动规)
从后往前找到与第i个字母相等的字母,判断两字母间是否是回文,i往后历遍,找到最长的回文字符串。时间复杂度比较高。
class Solution
{
public String longestPalindrome(String s)
{
String max = "";
if(s.length() == 0)
return max;
if(s.length() == 1)
return s;
for (int i = 0; i < s.length()-max.length(); i++)
{
char ch = s.charAt(i);
for(int j = s.length()-1; j >i; j--)//从后往前找
{
if(s.charAt(j) == ch) //字母相同,判断两字母间是否是回文
{
String str = s.substring(i, j+1);
if(isHuiWen(str))
{
//得到最长的回文字符串
max = str.length()>max.length()?str:max;
break;
}
}
}
}
return max.equals("")? s.substring(0,1):max;
}
private boolean isHuiWen(String str)
{
// TODO Auto-generated method stub
int j = str.length() -1;
for (int i = 0; i < str.length()/2; i++)
{
if(str.charAt(i) != str.charAt(j--))
return false;
}
return true;
}
}