public String longestPalindrome(String s) {
// 思路:动态规划,dp[i][j]表示s[i~j]是否为回文串,当i==j的时候,只有一个字符,显然是回文,也就是dp[i][i]=true
// 当i+1=j的时候,只有s[i]=s[j]他才是回文串,除这两种情况外,dp[i][j]要是true的话,必须dp[i+1][j-1]为true,且s[i]=s[j]
// 例如abbcbba,当i=0,j=6的是,要判断s[0~6]是否是回文串,先判断s[1~5]是否是回文,再看s[0]是否等于s[6]
if (s.length() <= 1)
return s;
boolean[][] dp = new boolean[s.length()][s.length()];
// 使用三个值来保存最长的那个回文子串位置
int left = 0;
int right = 0;
int max = 1;
for (int j = 1; j < s.length(); j++) {
dp[j][j] = true;
for (int i = 0; i < j; i++) {
//
if (i + 1 == j)
dp[i][j] = (s.charAt(i) == s.charAt(j));
else
dp[i][j] = (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]);
if (dp[i][j] && j - i + 1 > max) {
max = j - i + 1;
left = i;
right = j;
}
}
}
return s.substring(left, right + 1);
}
另一个解法:马拉车算法,时间复杂度只有O(n)
// 马拉车算法
public String longestPalindrome(String s) {
if (s.length() <= 1)
return s;
// 预处理,在每个字符的前后都加一个特殊字符#
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
sb.append("#");
sb.append(c);
}
sb.append("#");
// 若输入的s为aabba,那么警告处理后s变为#a#a#b#b#a#,这样做的目的是将其变为奇数长
s = sb.toString();
// 设置数组len,len[i]表示以s[i]为中心的回文串折叠起来的长度,比如#a#b#a#,那么len[3] =
// 4,因为#a#b#a#折叠起来是#a#b,长度为4
// len有一个性质,那就是len[i]-1表示s在未预处理之前的以i为中心的回文串长度,证明如下:经过预处理之后的s中,#总比字符个数多一个,那么假设
// 字符个数为x,那么#就为x+1,那么x+x+1=2*Len[i]-1,(2*len[i]-1是把折叠的展开),可得x=len[i]-1
int[] len = new int[s.length()];
len[0] = 1;
// 此外还要定义2个值,保存最长回文子串的位置信息,center表示最长回文串的中心,right表示最长回文子串的右边界
int center = 0;
int right = 0;
for (int i = 1; i < s.length(); i++) {
char c = s.charAt(i);
boolean flag = true; // flag表示是否需要重新求
if (i < right) { //当前位置i若在最长回文字符串右边界覆盖范围之内
int left_mirror = 2 * center - i; //求i关于center的对称点,因为对称点的len我们已经求出来了,可以利用
//如果i加上len[left_mirror]超过了最右边界,说明i这个位置的回文串需要重新计算
if (i + len[left_mirror] > right) {
len[i] = right - i + 1;
} else { //否则,i加上len[left_mirror]超不过右边界,就可以用它的对称点的len值,他们是相等的
len[i] = len[left_mirror];
flag = false;
}
}
//需要重新计算的话,就是从i向两边发散
if (flag) {
while (i - len[i] >= 0 && i + len[i] < s.length() && s.charAt(i - len[i]) == s.charAt(i + len[i]))
len[i]++;
// 更新最长的回文串对应的中心
while (len[i] > right - center + 1) {
center = i;
right = center + len[i] - 1;
}
}
}
// 输出结果
StringBuilder res = new StringBuilder();
for (int i = center - len[center] + 2; i <= center + len[center] - 1; i += 2)
res.append(s.charAt(i));
return res.toString();
}
做个记录!