题目: https://www.acwing.com/problem/content/4699/
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e6+5;
const int Mod = 131;
string s;
int f1[N],f2[N],p[N];
int ans,l,r,mid;
int Hash1(int i,int j){//正字符串的哈希值
return (f1[j]-f1[i-1]*p[j-i+1]);
}
int Hash2(int i,int j){//反字符串的哈希值
return (f2[i]-f2[j+1]*p[j-i+1]);
}
void init(){
p[0]=1;//p^0为1
for(int i=1;i<=N-1;i++)
p[i]=p[i-1]*131;//P进制的位值
}
int get(int h[],int l,int r){
return h[r]-h[l-1]*p[r-l+1];
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
init();
ans=0;
cin>>s;
s=' '+s;
int len=s.size();
f2[len+1]=0;//初始化要注意,不然的话容易GG
for(int i=1;i<=len;i++){
f1[i]=f1[i-1]*Mod+(s[i]-'a'+1);//前缀和
}
for(int i=len;i>=1;i--){
f2[i]=f2[i+1]*Mod+(s[i]-'a'+1);//后缀和
}
for(int i=1;i<=len;i++){
l=0,r=min(i-1,len-i);//二分枚举长度为奇数的字符串 记住这里l一定要为0,不然的话,你会发现最后一个数据会卡死你.
while(l<r){
mid=l+r+1>>1;
if(Hash1(i-mid,i-1)==Hash2(i+1,i+mid)){//如果这是一个回文串的话
l=mid;
}
else{
r=mid-1;
}
}
ans=max(l<<1|1,ans);//算出最大长度
l=0,r=min(i-1,len-i+1);//偶数字符串
while(l<r){
mid=l+r+1>>1;
if(Hash1(i-mid,i-1)==Hash2(i,i+mid-1)){//check判断
l=mid;
}
else{
r=mid-1;
}
}
ans=max(l<<1,ans);//偶数字符串只需要*2
}
cout<<ans<<"\n";
return 0;
}
练习:
https://atcoder.jp/contests/abc284/tasks/abc284_f
字符串双哈希模板:
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
bool isprime(int n) {
if (n <= 1) return false;
for (int i = 2; i * i <= n; i++)
if (n % i == 0)
return false;
return true;
}
int findPrime(int n) {
while (!isprime(n))
n++;
return n;
}
template<int N>
struct StringHash {
static array<int, N> mod;
static array<int, N> base;
vector<array<int, N>> p, h;
StringHash() = default;
StringHash(const string& s) {
int n = s.size();
p.resize(n);
h.resize(n);
fill(p[0].begin(), p[0].end(), 1);
fill(h[0].begin(), h[0].end(), 1);
for (int i = 0; i < n; i++)
for (int j = 0; j < N; j++) {
p[i][j] = 1ll * (i == 0 ? 1ll : p[i - 1][j]) * base[j] % mod[j];
h[i][j] = (1ll * (i == 0 ? 0ll : h[i - 1][j]) * base[j] + s[i]) % mod[j];
}
}
array<int, N> query(int l, int r) {
assert(r >= l - 1);
array<int, N> ans{};
if (l > r) return {0, 0};
for (int i = 0; i < N; i++) {
ans[i] = (h[r][i] - 1ll * (l == 0 ? 0ll : h[l - 1][i]) * (r - l + 1 == 0 ? 1ll : p[r - l][i]) % mod[i] + mod[i]) % mod[i];
}
return ans;
}
};
constexpr int HN = 2;
template<>
array<int, 2> StringHash<HN>::mod =
{findPrime(rng() % 900000000 + 100000000),
findPrime(rng() % 900000000 + 100000000)};
template<>
array<int, 2> StringHash<HN>::base {13331, 131};
using Hashing = StringHash<HN>;