/**
* 中心扩散法解回文串问题
* @param s
* @return
*/
public String longestPalindrome(String s) {
// 获取长度
int len = s.length();
// 如果长度是0或者1直接返回
if(len == 0 || len == 1){
return s;
}
// 将字符串转字符数组
char[] chs = s.toCharArray();
// 定义起始坐标
int start = 0;
// 定义最大长度
int maxLen = 1;
// 从0开始遍历
for(int i=0;i<len;i++) {
// 从i扩散获取最大长度
int midLen = expand(chs, i, i);
// 从i,i+1作为中心向外扩散获取最大长度
int doubleLen = expand(chs, i, i+1);
// 获取二者最大长度
int tmpMax = Math.max(midLen, doubleLen);
// 如果二者的最大长度 大于 变量最大长度,则替换相关数据
if(tmpMax>maxLen){
maxLen = tmpMax;
// 起始下标取 以当前下标作为中心 的总长度为tmpMax的起始点作为下标
// 如果 以i=5为单个中心点,3位最大长度,那么理论上其实下标应该为4 因为应该是 4 5 6 三个下标组成的字符串
// 如果 以i=5, i+1=6 为双中心点, 那么tmpMax必为偶数,如4,那么其实下标应该为 4 5 6 7
// 所以如果是奇数个字符组成的,其实start =i - tmpMax/2;也是对的,当然使用 start = i - (tmpMax-1)/2 也是对的,因为是向下取整
// 但当时偶数时,因为i是左侧的点,那么其实应该少走一个点,也就是start = i - tmpMax/2 = 5-4/2=3就不对了,削弱1,就可以得到正确的下标
// 所以这里统一用 i - (tmpMax-1)/2 作为其实下标
start = i - (tmpMax-1) / 2;
}
}
return new String(chs, start, maxLen);
}
private int expand(char[] chs, int start, int end) {
// 以 start 和 end 为中心向两边扩散,当累加完之后不正确时,其实此时的数据是脏数据,所以在结果返回时,我们应该去掉2长度的脏数据
// 也就是,原本start到end的长度应该为 end - start + 1 ,而此时因为是不符合要求的长度,所以,我们应该减掉2来 获取最近一次符合条件的长度
// 因此结果返回为 end - start +1-2 = end - start - 1
while(start>=0 && end<chs.length && chs[start]==chs[end]){
start--;
end++;
}
return end-start-1;
}
遍历每个下标,每次以该下标为中心的向外扩展的最长奇数个字符的字符串
和以该下标及该下标的下一个下标为中心向外扩展的最长偶数个字符的字符串,
取最长一个,和当前结果变量作比较,如果是更长的长度,那么替换结果变量
最终获取最长的 回文 子串