马拉松算法 - 最长回文子串-java
算法解释的链接
链接: link.
下面是java代码。
// An highlighted block
class Solution {
public String longestPalindrome(String s) {
String str = preHandleString(s);
int len = str.length();
//当前的最右和最右的中心点
int right = 0;
int rightCenter = 1;
//用于保存以i为中心的时候的最长半径
int[] halfLenArr = new int[len];
//历史的最长子串的中心和长度
int center = 0;
int longestHalf = 0;
for(int i = 1 ;i < len - 1; i ++){
//需不需要扩展
boolean needCala = true;
if(right > i){
int left = 2 * rightCenter - i;
halfLenArr[i] = Math.min(halfLenArr[left], right - i);
if(i + halfLenArr[i] < right ){
//如果当前的中心加半径在最右的范围内,则不用扩展,因为扩展后必不回文
needCala = false;
}
}
if(needCala){
//这里不用考虑边界是因为初始化字符串的处理
while (str.charAt(i - halfLenArr[i]) == str.charAt(i + halfLenArr[i])){
halfLenArr[i] ++;
}
halfLenArr[i] --;
right = i + halfLenArr[i];
rightCenter = i;
if(halfLenArr[i] > longestHalf){
center = i;
longestHalf = halfLenArr[i];
}
}
}
//取结果需要跳过中间的#,所以是每次跳两格
StringBuffer stringBuffer = new StringBuffer();
for(int i = center - longestHalf + 1; i < center + longestHalf;i += 2 ){
stringBuffer.append(str.charAt(i));
}
return stringBuffer.toString();
}
//初始化字符串
private String preHandleString(String s){
StringBuffer stringBuffer = new StringBuffer();
int length = s.length();
//添加@和$是为了上面循环不用考虑边界问题,因为到边界就会不等于了
stringBuffer.append("@#");
for(int i = 0 ; i < length ; i ++){
stringBuffer.append(s.charAt(i));
stringBuffer.append('#');
}
stringBuffer.append("$");
return stringBuffer.toString();
}
}