题意
和Longest Substring Without Repeating Characters恰巧相反,计算出重复字符串的最长回文子串。并返回首个最长重复子串。
我的思路及代码
- 暴力法:顾名思义遍历所有子串,判断是否为回文字符串。以下是我的暴力代码,遍历子串效率为O(n^2),判断是否为回文字符串效率为O(n),所以总体效率为O(n^3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public class Solution {
public String longestPalindrome(String s) {
if(s==null||s.equals("")) return s;
int start=0,end=1;
for(int i=0;i<s.length()-1;i++){
if(s.length()-i<end-start)
break;
for(int j=s.length()-1;j>=i+1;j--){
if(s.charAt(i)==s.charAt(j)){
if(isHui(s.substring(i+1,j))){
if((j-i+1)>(end-start)) {
start = i;
end = j+1;
}
break;
}
}
}
}
return s.substring(start,end);
}
public boolean isHui(String str){
if(str.equals("")||str.length()==1) return true;
for(int m = 0;m<str.length()/2;m++){
if(str.charAt(m)!=str.charAt(str.length()-m-1))
return false;
}
return true;
}
}
注意内部循环是从尾部向前遍历的。如果是
- 动态规划:暴力法中其实很多判断回文字符串是重复的,怎么来优化呢。可以提供一个二维数组来记录是否为回文字符串的状态。需要O(n^2)空间状态。
因为回文字符串的子字符串也是回文串。s[i,j]是回文,s[i+1,j-1]肯定也是回文
首先定义状态方程和转移方程:
P[i,j]=false:表示子串[i,j]不是回文串。P[i,j]=true:表示子串[i,j]是回文串。
P[i,i]=true:当且仅当P[i+1,j-1] = true && (s[i]==s[j])
我想到了用动态规划来做,但是没想出来是因为思维固化了。固化的地方,一直想不明白遍历字符串的时候,内部字符串是否为回文串,没法在之前的循环遍历中确定,实际上只需要换一种遍历方式即可,这种遍历方式是以回文串的长度,由短及长,这样在遍历到长的回文串时可以用短的回文串状态来判断。
1 | public static String findLongestPalindrome1(String s){ |
- 中心扩展法
中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。
但是要考虑两种情况:
1、像aba,这样长度为奇数。
2、像abba,这样长度为偶数。
1 | public static String findLongestPalindrome2(String s){ |