【ybtoj 高效进阶 2.2】 【hash】 回文子串
题目
解题思路
做正反两次hash
枚举中心二分最大回文子串
代码
在这里插入代码#include <iostream>
#include <cstring>
#include <cstdio>
#define ull unsigned long long
using namespace std;
char s[10400010];
ull n, ans, len, l, r, mid;
ull power[1000010], zhash[1000010], fhash[1000010];
int main() {
scanf("%s", s + 1);
while (s[1] != 'E') {
memset(zhash, 0, sizeof(zhash));
memset(fhash, 0, sizeof(fhash));
memset(power, 0, sizeof(power));
n++;
ans = 0;
len = strlen(s + 1);
power[0] = 1ull;
for (int i = 1; i <= len; i++) {
power[i] = power[i - 1] * 131ull;
zhash[i] = zhash[i - 1] * 131ull + s[i] - 'a'; //正序hash
}
for (int i = len; i > 0; i--) fhash[i] = fhash[i + 1] * 131ull + s[i] - 'a'; //倒序hash
for (int i = 1; i <= len; i++) {
l = 0, r = len;
while (l <= r) {
//奇数
mid = (l + r) / 2;
if (i - mid < 1 || i + mid > len) {
r = mid - 1;
continue;
}
if (zhash[i] - zhash[i - mid - 1] * power[mid + 1] ==
fhash[i] - fhash[i + mid + 1] * power[mid + 1]) {
l = mid + 1;
ans = max(ans, mid * 2 + 1);
} else
r = mid - 1;
}
l = 0, r = len;
while (l <= r) {
//偶数
mid = (l + r) / 2;
if (i - mid < 0 || i + mid > len) {
r = mid - 1;
continue;
}
if (zhash[i] - zhash[i - mid] * power[mid] ==
fhash[i + 1] - fhash[i + mid + 1] * power[mid]) {
l = mid + 1;
ans = max(ans, mid * 2);
} else
r = mid - 1;
}
}
printf("Case %lld: %lld\n", n, ans);
scanf("%s", s + 1);
}
return 0;
}