代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 1e9+7;
const ll N = 4e5+100;
const ll base1 = 131, base2 = 137;
ll len;
char c[N];
ll p1[N], p2[N];
ll h1[N], h2[N];
void init() {
p1[0] = p2[0] = 1;
for (ll i = 1; i <= len; i++) p1[i] = (p1[i - 1] * base1) % mod;
for (ll i = 1; i <= len; i++) p2[i] = (p2[i - 1] * base2) % mod;
for (ll i = 1; i <= len; i++) h1[i] = (h1[i - 1] * base1 + (c[i] - 'a' + 1)) % mod;
for (ll i = 1; i <= len; i++) h2[i] = (h2[i - 1] * base2 + (c[i] - 'a' + 1)) % mod;
}
pair<ll, ll> get_hash(ll l, ll r) {
ll res1 = (h1[r] - (h1[l - 1] * p1[r - l + 1]) % mod + mod) % mod;
ll res2 = (h2[r] - (h2[l - 1] * p2[r - l + 1]) % mod + mod) % mod;
return {res1, res2};
}
pair<ll, ll> get_rev_hash(ll l, ll r) {
ll new_l = len - r + 1;
ll new_r = len - l + 1;
return get_hash(new_l, new_r);
}
bool check(ll x) {
if (x == 0) return true;
ll l = 1, r = x;
auto h_normal = get_hash(l, r);
auto h_rev = get_rev_hash(l, r);
return h_normal == h_rev;
}
int main() {
cin >> len;
cin >> (c + 1);
init();
ll l = 0, r = len, ans = 0;
while (l <= r) {
ll mid = (l + r) >> 1;
if (check(mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
cout << len - ans;
return 0;
}
大概思路是用二分枚举哈希回文串长度,用双哈希进行验证,检验即可。第一次写双哈希,可能错了。
ansi_j表示正/反着乘数为base_j的哈希值