求给定的一个字符串中的最大回文子串
一般第一想到的方法应该就是循环,回文就是以某个字符为中心向两侧扩展,并且两侧对称。
这样的解决方法执行时间复杂度会是O(
n
2
n^2
n2)。如何做到线性负责度呢。
那就是Manaker算法了。我这里只给出我的Java单个方法的实现,分析的内容可以参考给出的链接。
public String longestPalindrome(String s) {
// 首位分别添加'$', '@'防止边界异常
StringBuilder t = new StringBuilder("$");
for (int i = 0; i < s.length(); i++) {
t.append('#');
t.append(s.charAt(i));
}
t.append('#');
t.append('@');
int right = 0; // 最新回文子串右侧边界
int center = 0; // 最新回文子串中心位置
int len = t.length();
int[] p = new int[len];
for (int i = 1; i < len - 1; i++) {
// 利用已经计算过的回文信息,加快运行时间
// 在以center为中心回文范围内的i,可以利用回文性质,找到
// 其对于center对称的点 '2 * center - i' 的回文数据,减少
// 扩展次数,从而加快搜索
if (i < right) p[i] = Math.min(p[2 * center - i], right - i);
// 中心扩展,p[i] + 1 => 扩展的长度
while (t.charAt(i - (p[i] + 1)) == t.charAt(i + (p[i] + 1))) p[i]++;
if (i + p[i] > right) { // 最新回文下表更新
center = i;
right = i + p[i];
}
}
int longest = 0;
int index = 0;
for (int i = 1; i < p.length - 1; i++) {
if (p[i] > longest) {
longest = p[i];
index = i;
}
}
return s.substring((index - longest) / 2, (index + longest) / 2);
}
参考:
- 基本概念
- Manaker算法
- leetcode上回文分析
- 其他比较详细的分析