#include <iostream>
#include <string>
using namespace std;
char arr1[1001000];
char arr2[1001000];
char manacher[2002000];
//int m[1001000][1000100]={0};
int p[2000010] = {0};//p[j]串长度
string arr;
int dex = 0;
//poj 3974
int main() {
while (cin >> arr){
if(arr == "END") break;
dex++;
// cout << arr <<endl;
// cout <<"chuan:";
int len = arr.length();
for (int i = 1; i <= len; ++i) {
arr1[i] = arr[i-1];
arr2[i] = arr[len-i];
// cout << arr2[i];
}
//动态规划算法
/*for (int j = 1; j < len; ++j) {
m[j][j] = 1;
arr1[j+1] == arr1[j] ? m[j][j+1] = 1 : m[j][j+1] = 0;
}
for (int k = len-2; k > 0; --k) {//起点
for (int i = k+2; i <= len; ++i) {//终点
(arr1[k] == arr1[i]) && (m[k+1][i-1] == 1) ? m[k][i] = 1 : m[k][i] = 0;
}
}
int sumMax = 0;
for (int l = 1; l <= len; ++l) {
for (int i = len; i > 0; --i) {
if(m[l][i]){
if(i-l > sumMax) sumMax = i-l;
}
}
}*/
//manacher算法
// 本质上是利用了p[id]这个已知的回文串的左右对称性质,在考虑[j]这个点的时候,包含在p[id]内的就不用重复考虑,直接跳到后面的部分;
// 主要就是比较[j]关于id这个点的对称点[2*id-j]这个点的 p[2*id-j]] 与 p[id]+id-j 的关系,分为3种,大于,小于,等于。考虑这三种关系p[j]有不同的取值
// 原帖:http://blog.csdn.net/xingyeyongheng/article/details/9310555 第三种情况我觉得没有可能继续扩展了,因为用证明第一种的方法可以证明这样扩展是错的。
// 加#后为#a#b#c#,
int ii = 1;
int maxLen = 0;
for (int k = 1; k <= 2*len+1; k = k+2) {
manacher[k] = '#';
if (ii > len) break;//注意此处边界的处理,要考虑好
manacher[k+1] = arr1[ii++];
}
manacher[0] = '*';
int id = 1;//回文串中心
int mx = 0;//串边界
for (int j = 1; j <= 2*len+1; ++j) {
if (j < p[id]+id){
p[j] = min(p[2*id-j] , p[id]+id-j);
} else {
p[j] = 1;
}
while (manacher[j+p[j]] == manacher[j-p[j]])
p[j]++;
if (p[j]+j > p[id]+id) id = j;
if (maxLen < p[j]) maxLen = p[j];
}
cout << "Case " << dex << ": " << maxLen-1 << endl;
}
//cout << "Hello, World!" << endl;
return 0;
}
动态规划算法:m[i][j]为i开始到j结束这段子串为回文串时依赖,m[i+1][j-1]要为回文串且arr[i]==arr[j];注意计算的方向