在给定字符串末尾添加一个字符串,生成回文串,且回文串长度最短
可以求字符串包含到最右边的字符的最右回文右边界的中心,然后以此中心为基准,回文半径在左边不包含的部分加上即可
* 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 )); } }