import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { // 定义辅助变量 // 开始和结束下标用于最后输出结果 private static int start = 0; private static int end = -1; // 记录回文串最右和中间的位置 private static int right = -1; private static int center = -1; // 主函数 public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 获取输入字符串 String s = br.readLine(); // 对字符串进行预处理转换 StringBuffer buffer = new StringBuffer("#"); for (int i = 0; i < s.length(); i++) { buffer.append(s.charAt(i)); buffer.append("#"); } buffer.append("#"); s = buffer.toString(); // 预处理完毕 // 定义列表存储臂长 List<Integer> armLens = new ArrayList<>(); // 遍历字符串的每个位置,求出其所对应的最大臂长 for (int i = 0; i < s.length(); i++) { int curArmLen = 0; if (i <= right) { // 落点在某个回文串之内 int mirror = 2 * center - i; // 找到当前i关于center的镜像位置 // 在镜像臂长和边界臂长中选较小者,确保长度不越界 int minArmLen = Math.min(armLens.get(mirror), right - i); // 跳过此最小长度的字符数后,继续对比两端字符,以扩张当前位置的臂长 curArmLen = expand(s, i - minArmLen, i + minArmLen); } else { // 落点在回文串之外,直接从落点位置中心扩散,暴力求解 curArmLen = expand(s, i, i); } // 记录当前臂长 armLens.add(curArmLen); // 更新最右位置和中心位置 if (i + curArmLen > right) { center = i; right = i + curArmLen; } // 更新最长回文子串的开始和结束下标 if (curArmLen * 2 + 1 > end - start + 1) { // 长度大于原先的长度 start = i - curArmLen; end = i + curArmLen; } } // 遍历结束 // 拼接结果后输出其长度 StringBuffer ans = new StringBuffer(); for (int i = start; i <= end; i++) { if (s.charAt(i) != '#') { ans.append(s.charAt(i)); } } System.out.println(ans.toString().length()); } // 辅助函数,用于扩展回文字符串的长度,以当前位置的臂长所体现 private static int expand(String s, int left, int right) { while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { left--; right++; } // 减2是因为最后两指针都多移了一次 // 右指针减左指针的值为长度减1,刚好等于臂长的两倍(臂长 * 2 + 1中点 = 长度) return (right - left - 2) / 2; // 返回的结果即为臂长 } }