Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Input: "cbbd"
Output: "bb"
native的方法 2层循环 验证每一个可能的子字符串是否是回文,再加一层验证回文的函数要一层循环,总的是 O(n3)复杂度
public String longestPalindrome(String s) {
if(s==null) return null;
// String[][] dp= new String[1000][1000];
// Arrays.fill(dp,1);
int max=1;
String result=s.substring(0,1);
for(int i=0;i<s.length()-1;i++){
for(int j=i+1;j<s.length();j++){
String temp=s.substring(i,j+1);
if(ifPalin(temp)){
if(max<temp.length()){
max=temp.length();
result=temp;
}
if(max==s.length())
return result;
}
}
}
return result;
}
public boolean ifPalin(String s){
if(s==null) return true;
int start=0;
int end=s.length()-1;
while(start<end){
if(s.charAt(start++)!=s.charAt(end--)){
return false;
}
}
return true;
}
brutal force的算法把所有的可能的substring 都去做了验证是否事palindrome. 为了优化,我们首先分析如何能避免不必要的重复计算。
通过对回文性质的分析,我们可以看出来: 如果中间的某一段子串sub是回文,如果sub两侧的字符是一样的,那么作为一个整体也是回文。例如:
abcdcba : d是回文,cdc那么就是回文。 如果你再想一下,cdc是回文,两侧b是一样的,bcdcb也是回文。咦,那么abcdcba就是回文了呗。
通过上个例子我们直接知道了答案。这是特例,那么对于一般情况如何是好呢?所以第一个思路就是根据顺向的思维推导出来的:
我们申明一个dp[][]来储存状态。 对于dp[i][j]来说, 其意义就是 s.substring(i,j+1)是不是回文。
(1)既然我们不知道哪里为中心,向外拓展就能得到答案。那么就以每个字符为中心,向外拓展,保存一个最大的量,问题就解决了!
我们得初始化下dp, 单个字符是,所以dp[i][i]=true.
可是还有种情况, abcddcba,中间是两个,不是一个,这也能构成回文,这怎么办!
其实也好办,我们就看看s.charAt(i)==s.charAt(i+1),如果是,就是回文,我们就set dp[i][i+1]=true
有了基础的case,我们1层for循环移动中心点,用两个指针start,end,分别拓展这两种情况,来分析回文,即可找出最大值。
第一种,用dp的方法,dp的思路是用以前做出来的结果作为基础,然后推导出新的结果,首先要分析特例:
如果P[i,j]为真,当且仅当si-1,si-2...sj-1,sj这一个子串都为palindrome。例如:s[] = skrdjdre那么P[2][6] = true,因为s[2]=r=s[6],且djd为回文。
代码如下:
public String longestPalindrome(String s) {
if(s==null) return null;
boolean[][] dp= new boolean[s.length()][s.length()];
//define dp[i][j] is if s.substring(i,j+1) is palindrome:
int max=1;
String result=s.substring(0,1);
for(int i=0;i<s.length();i++){
dp[i][i]=true;
}
for(int i=0;i<s.length()-1;i++){
if(s.charAt(i)==s.charAt(i+1)){
dp[i][i+1]=true;
result=s.substring(i,i+2);
max=2;
}
}
for(int i=1;i<s.length()-1;i++){
int start=i-1,end=i+1; //aba的情况
while(start>=0 && end<=s.length()-1){
if(dp[i][i] && s.charAt(start)==s.charAt(end)){
dp[start][end]=true;
if(max<end-start+1){
max=end-start+1;
result=s.substring(start,end+1);
}
} else {
break;
}
start--;end++;
}
start=i-1;end=i+2; //abba的情况
while(start>=0 && end<=s.length()-1){
if(dp[i][i+1] && s.charAt(start)==s.charAt(end)){
dp[start][end]=true;
if(max<end-start+1){
max=end-start+1;
result=s.substring(start,end+1);
}
} else{
break;
}
start--;end++;
}
}
return result;
}
1687

被折叠的 条评论
为什么被折叠?



