链接
题目描述
如果一个字符串正着读和倒着读是一样的,则称它是回文的。
给定一个长度为 N的字符串S,求他的最长回文子串的长度是多少。
样例输入
abcbabcbabcba
abacacbaaaab
END
样例输出
Case 1: 13
Case 2: 6
思路
正反两遍求出hash值,然后枚举点向两边二分求出最大长度
代码
#include <cstdio>
#include <cstring>
#include <iostream>
#define ull unsigned long long
using namespace std;
int l, r, mid, t, len, ans;
ull c[1000050], z[1000050], f[1000050];
char s[1000050];
void work() {
memset(z, 0, sizeof(z));
memset(f, 0, sizeof(f));
ans = 1;
for (int i = 0; i < len; ++i) z[i + 1] = z[i] * 131 + s[i];
for (int i = len; i > 0; --i) f[i] = f[i + 1] * 131 + s[i - 1];
for (int i = 1; i <= len; ++i) {
l = 0;
r = (len >> 1) + 1;
while (r >= l) {
mid = (l + r) >> 1;
if (i - mid <= 0 || i + mid > len)
r = mid - 1;
else if (z[i] - z[i - mid - 1] * c[mid + 1] == f[i] - f[i + mid + 1] * c[mid + 1]) {
ans = max(ans, mid * 2 + 1);
l = mid + 1;
} else
r = mid - 1;
}
l = 0;
r = (len >> 1) + 1;
if (z[i] - z[i - 1] * 131 == f[i + 1] - f[i + 2] * 131)
ans = max(ans, 2);
while (r >= l) {
mid = (l + r) >> 1;
if (mid == 0)
break;
if (i - mid + 1 <= 0 || i + mid > len)
r = mid - 1;
else if (z[i] - z[i - mid] * c[mid] == f[i + 1] - f[i + mid + 1] * c[mid]) {
ans = max(ans, mid * 2);
l = mid + 1;
} else
r = mid - 1;
}
}
printf("Case %d: %d\n", t, ans);
}
int main() {
char cc;
c[0] = 1;
for (int i = 1; i <= 1000000; ++i) c[i] = c[i - 1] * 131;
cc = getchar();
len = 0;
while (cc != ' ' && cc != '\n') {
s[len] = cc;
cc = getchar();
++len;
}
t = 1;
while (s[0] != 'E') {
work();
++t;
cc = getchar();
len = 0;
while (cc != ' ' && cc != '\n') {
s[len] = cc;
if (cc >= 'A' && cc <= 'Z')
return 0;
cc = getchar();
++len;
}
}
}