网上流行的做法是在两两字符之间加上一个 # 然后全部当做奇数长度的回文串来求。
但是我是对于每个回文点 i 分别二分奇数长度最多为多少,和偶数长度最多为多少,然后分别取 max,但是却出现了答案为偶数但是我输出比其小1的情况。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N = 1e6 + 10;
const ull pri = 131;
ull h[N], h2[N], p[N] = {1};
ull subhs (int l, int r) {
return h[r] - h[l - 1] * p[r - l + 1];
}
ull subhs2(ull l, ull r) {
return h2[l] - h2[r + 1] * p[r - l + 1];
}
string s;
void init() {
for (int i = 1; i <= (int)s.size(); i ++) h[i] = h[i - 1] * pri + s[i - 1];
for (int i = (int)s.size() ; i >= 1; i --) h2[i] = h2[i + 1] * pri + s[i - 1];
}
signed main() {
ios::sync_with_stdio(0);
for (int i = 1; i <= 1e6; i ++) p[i] = p[i - 1] * pri;
int cas = 0;
while(cin >> s) {
if(s == "END") return 0;
init();
int n = s.size(), ans = 0;
for (int i = 1; i <= n; i ++) {
// 对于奇数长度的回文串
int l = 1, r = min(i - 1, n - i);
while(l < r) {
int mid = (l + r + 1) >> 1;
if(subhs(i - mid, i - 1) == subhs2(i + 1, i + mid)) l = mid;
else r = mid - 1;
}
if(subhs(i - l, i - 1) == subhs2(i + 1, i + l)) ans = max(ans, l * 2 + 1);
// 对于偶数长度的回文串
if(i == n) continue;
l = 1, r = min(i, n - i);
while(l < r) {
int mid = (l + r + 1) >> 1;
if(subhs(i - mid + 1, i) == subhs2(i + 1, i + mid)) l = mid;
else r = mid - 1;
}
if(subhs(i - l + 1, i) == subhs2(i + 1, i + l)) ans = max(ans, l * 2);
}
cout << "Case " << ++ cas << ": " << ans << endl;
}
}