马拉车Manacher算法总结
- 专门解决回文问题的算法!
- 记录每个元素半径长度以及最右的位置R并保持更新这两个变量!
- 记录对应的中点位置C
给一个字符串,首先找出对称轴元素!不过元素为偶数个的时候对称轴会不存在!如何把奇偶统一?在字符串之间加#字符全转换为奇个数!
回文半径数组----prrArr[]
、
回文半径数组、之前扩地所有所到达的最右边界位置以及对应的中心点
- 有了R,C,prrArr[]信息,就要判断i的位置
第一种情况 i > R在外部
很明显,直接向外扩张,更新R
第二种情况 i < R 在R内部
1、半径也在R内
直接找i的对称点i’,两个的答案是一样的!
2、回文一部分在半径外部
看图得知 X==Y,Y = =Z,P != X !=Z
答案就是i~R
第三种压线了!
判断R后一个和R‘前一个是否相等就行了!
class Solution5 {
public static void main(String[] args) {
String s = "babad";
Solution5 solution = new Solution5();
String s1 = solution.longestPalindrome(s);
System.out.println(s1);
}
public String longestPalindrome(String s) {
//把字符串处理成adb--->#a#b#b#
StringBuffer t = new StringBuffer("#");
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
t.append(c);
t.append('#');
}
s = t.toString();
//定义
//回文半径数组
int[] prrArr = new int[s.length()];
int Center = 0;
int Right = -1;
int start = 0;
int maxLen = 0;
//int max = Integer.MAX_VALUE;
for (int i = 0; i < s.length(); i++) {
//i在不在最大半径里面?在的话就半径加到Right!
//能不能继续向下加先不着急!不在R里面的话就只能+1
prrArr[i] = Right > i ?Math.min(prrArr[2*Center - i],Right - i) :1;
while(i + prrArr[i] < s.length() && i- prrArr[i] > -1){
if (s.charAt(i + prrArr[i]) == s.charAt(i - prrArr[i])){
prrArr[i]++;
}else {
break;
}
}
//更新Right
if(i+ prrArr[i] > Right){
Right = i + prrArr[i];
Center = i;
}
//max = Math.max(max, prrArr[i]);
if (prrArr[i]*2 + 1> maxLen - start){
start = i - prrArr[i];
maxLen = i + prrArr[i];
}
}
StringBuffer ans = new StringBuffer();
for (int i = start + 1; i <= maxLen - 1; ++i) {
if (s.charAt(i) != '#') {
ans.append(s.charAt(i));
}
}
return ans.toString();
//return s;
}
}