// 预处理字符串,在两个字符之间加上#
private String preHandleString(String s) {
StringBuffer sb = new StringBuffer();
int len = s.length();
sb.append('#');
for(int i = 0; i < len; i++) {
sb.append(s.charAt(i));
sb.append('#');
}
return sb.toString();
}
// 寻找最长回文字串
public String findLongestPlalindromeString(String s) {
// 先预处理字符串
String str = preHandleString(s);
// 处理后的字串长度
int len = str.length();
// 右边界
int rightSide = 0;
// 右边界对应的回文串中心
int rightSideCenter = 0;
// 保存以每个字符为中心的回文长度一半(向下取整)
int[] halfLenArr = new int[len];
// 记录回文中心
int center = 0;
// 记录最长回文长度
int longestHalf = 0;
for(int i = 0; i < len; i++) {
// 是否需要中心扩展
boolean needCalc = true;
// 如果在右边界的覆盖之内
if(rightSide > i) {
// 计算相对rightSideCenter的对称位置
int leftCenter = 2 * rightSideCenter - i;
// 根据回文性质得到的结论
halfLenArr[i] = halfLenArr[leftCenter];
// 如果超过了右边界,进行调整
if(i + halfLenArr[i] > rightSide) {
halfLenArr[i] = rightSide - i;
}
// 如果根据已知条件计算得出的最长回文小于右边界,则不需要扩展了
if(i + halfLenArr[leftCenter] < rightSide) {
// 直接推出结论
needCalc = false;
}
}
/* 中心扩展 */
if(needCalc) {
int left = i - 1 - halfLenArr[i];
int right = i + 1 + halfLenArr[i];
while( left >= 0 && right < len) {
if(str.charAt(right) == str.charAt(left)) {
halfLenArr[i]++;
} else {
break;
}
}
// 更新右边界及中心
rightSide = i + halfLenArr[i];
rightSideCenter = i;
// 记录最长回文串
if(halfLenArr[i] > longestHalf) {
center = i;
longestHalf = halfLenArr[i];
}
}
}
// 去掉之前添加的#
StringBuffer sb = new StringBuffer();
for(int i = center - longestHalf + 1; i <= center + longestHalf; i += 2) {
sb.append(str.charAt(i));
}
return sb.toString();
}
网友评论