Manacher回文算法
- leetcode5. 最长回文子串
- Manacher 算法
- manacher 算法
leetcode5. 最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
Manacher 算法
介绍下Manacher算法:
Manacher 算法是一种用于寻找最长回文子串的算法。它的时间复杂度为 O(n),其中 n 是字符串的长度。以下是 Manacher 算法的基本步骤:
- 初始化一个字符串,其中包含一个长度为 n+1 的回文串,以使得字符串的中间字符为字符串的中间字符,例如:P=“banana”。
- 找到字符串 P 的中心字符,将其标记为 center。
- 从字符串的两端开始遍历 P,对于每个字符,如果其与 center 的距离大于字符串的长度的一半,则将该字符移动到与 center 对齐的位置,即将其插入到 P 中相应位置。
- 在 P 中找到最长的回文子串的右边界 max_right,左边界为 center。
- 对于每个字符,如果其与 center 的距离小于等于 max_right 与 center 的距离减去 1,则将该字符的回文半径(即该字符与 center 的距离减去 max_right 与 center 的距离)加入到一个栈中。
- 遍历栈中的回文半径,对于每个半径 r,如果其左侧有一个半径为 r-1 的回文子串,则可以扩展该回文子串,直到其与 center 的距离为 r。
- 最终得到的字符串就是原字符串的最长回文子串。
Manacher 算法的关键在于利用回文串的特性,将字符串中的字符移动到合适的位置,以便于后续的回文子串的扩展。
manacher 算法只用于计算回文字符串,都是固定代码,
因此直接看代码吧.
代码演示
class Solution {
public String longestPalindrome(String s) {
return manacher(s);
}
public static String manacher(String s){
if (s == null || s.length() == 0){
return null;
}
char[] str = manacherString(s);
int R = -1;
int C = -1;
int[] pArr = new int[str.length];
int max = Integer.MIN_VALUE;
int pos = 0;
for (int i = 0; i < str.length;i++){
pArr[i] = R > i ? Math.min(pArr[2 * C - i],R - i) : 1;
while(i + pArr[i] < str.length && i - pArr[i] > -1){
if (str[i + pArr[i]] == str[i - pArr[i]] ){
pArr[i]++;
}else {
break;
}
}
if (i + pArr[i] > R){
R = i + pArr[i];
C = i;
}
if (max < pArr[i]){
pos = i;
max = pArr[i];
}
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = pos - max + 1; i < pos + max; i++){
if (str[i] != '#'){
stringBuilder.append(str[i]);
}
}
return stringBuilder.toString();
}
public static char[] manacherString(String s){
char[] chars = s.toCharArray();
int index = 0;
char[] manacher = new char[chars.length * 2 + 1];
for (int i = 0; i < manacher.length;i++){
manacher[i] = (i & 1) == 0 ? '#' : chars[index++];
}
return manacher;
}
}
manacher 算法
Manacher算法 – 回文长度算法