题目描述:
思路:一开始想的是用两个字符串最长公共子串来做,一个字串是给定的,另一个字串是给定的字串的逆序。但是最后解答错误。[“aacdefcaa”]这个的最长回文子串是aa,如果按最长公共子串来做得到的是acc。
先附上按最长公共字串做法的代码:
class Solution {
public static void main(String[] args) {
String s="abb";
System.out.println(new Solution().longestPalindrome(s));
}
public String longestPalindrome(String s) {
if (s.equals(""))return "";
int len=s.length();
int [][] ch=new int [len][len];
int maxlength=1;
int maxx=0;
String str="";
for (int i=0;i<len;i++){
if (s.charAt(i)==s.charAt(len-1)){
ch[0][i]=1;
}
if (s.charAt(len-i-1)==s.charAt(0)){
ch[i][0]=1;
}
}
for (int i=1;i<len;i++){
for (int j = 1; j < len; j++) {
if (s.charAt(len-i-1)==s.charAt(j)){
ch[i][j]=ch[i-1][j-1]+1;
if (ch[i][j]>maxlength){
maxlength=ch[i][j];
maxx=j;
}
}
}
}
for (int i=maxx-(maxlength-1);i<=maxx;i++){
str=str+s.charAt(i);
}
return str;
}
}
本来以为这个方法没有办法解出来了,但是看了下评论区,可以在长度增加时候进行一个是否是回文子串的判定。附上作者的做法:
作者的代码:
class Solution {
public String longestPalindrome(String s) {
if (s.equals(""))
return "";
String origin = s;
String reverse = new StringBuffer(s).reverse().toString();
int length = s.length();
int[] arr = new int[length];
int maxLen = 0;
int maxEnd = 0;
for (int i = 0; i < length; i++)
/**************修改的地方***************************/
for (int j = length - 1; j >= 0; j--) {
/**************************************************/
if (origin.charAt(i) == reverse.charAt(j)) {
if (i == 0 || j == 0) {
arr[j] = 1;
} else {
arr[j] = arr[j - 1] + 1;
}
/**************修改的地方***************************/
//之前二维数组,每次用的是不同的列,所以不用置 0 。
} else {
arr[j] = 0;
}
/**************************************************/
if (arr[j] > maxLen) {
int beforeRev = length - 1 - j;
if (beforeRev + arr[j] - 1 == i) {
maxLen = arr[j];
maxEnd = i;
}
}
}
return s.substring(maxEnd - maxLen + 1, maxEnd + 1);
}
}
最后看一下官方的解法:
1.暴力法:得到所有的子串并同时判定子串是否是回文子串
时间复杂度O(n^3)
空间复杂度O(1)
2.中心散列法
有些类似暴力法,但是时间复杂度有所改善。首先一个回文子串长度可以是奇数或偶数两种情况,分别将给定的字符串的每个字符当作回文子串的中心,之后判定每个字符为中心的回文子串的最长长度,得到结果。
时间复杂度O(n^2)
空间复杂度O(1)
3.动态规划
动态规划需要判定的情况比较复杂
以此类推
4.Manacher算法(专用来查找最长回文子串)
emmm算法比较复杂,暂时放弃。。。。