在给定字符串末尾添加一个字符串,生成回文串,且回文串长度最短
可以求字符串包含到最右边的字符的最右回文右边界的中心,然后以此中心为基准,回文半径在左边不包含的部分加上即可
* 2111123 --> 2111123211112
* 32112 --> 321123
* 3211233 --> 321123321123
即求得是包含最后一个字符在内的最长回文直径。
注意:在最后末尾添加字符串时,要记得是将字符串反向添加进去。
延伸到的最右边的那个字符的回文半径flags[center] (即为以center为中心的原字符串的回文直径。)
str.length() - flags[center] + 1就是需要补充的字符串长度
public class Manacher_ShortestEnd {
public static String shortestEnd(String str){
if(str == null || str.length() == 0) return str;
char[] ch = new char[str.length() * 2 + 1];
int index = 0;
for(int i = 0; i < ch.length; i++){
ch[i] = (i & 1) == 0 ? '#' : str.charAt( index++ );
}
int[] flags = new int[ch.length];
int maxRight = 0;
int center = 0;
for(int i = 0; i < ch.length; i++){
flags[i] = maxRight > i ? Math.min(flags[2 * center - i], maxRight - i) : 1;
while(i - flags[i] >= 0 && i + flags[i] < ch.length){
if(ch[i - flags[i]] == ch[i + flags[i]]){
flags[i]++;
}
else break;
}
if(i + flags[i] > maxRight){
maxRight = i + flags[i];
center = i;
if(maxRight == ch.length - 1){
break;
}
}
}
char[] res = new char[str.length() - flags[center] + 1];
for(int i = 0; i < res.length; i++){
res[res.length - 1 - i] = ch[i * 2 + 1];
}
str = str + String.valueOf( res );
return str;
}
public static void main(String[] args){
String str = "32111233";
System.out.println(shortestEnd( str ));
}
}