Mirrored String II Gym - 101350I (二分+hash)
由于不会马拉车求最长回文子串,于是就只能用二分了。然后由于长度为奇数的回文子串不存在,不代表更长的长度为偶数的回文子串不存在。但是长度为奇(偶)数的回文子串不存在,更长的长度为奇(偶)数的回文子串一定不存在,长度为奇(偶)数的回文子串存在,更短的长度为奇(偶)数的回文子串一定存在,所以可以想到对奇偶长度分开二分。比如说huuf,长度为3的回文子串是不存在的,但是长度为4的回文子串是存在的,这就不具有二分的单调性了。check函数里这个c数组是标记数组,标记i位置能否作为起点。
#include<bits/stdc++.h>
using namespace std;
#define fuck(x) cout<<#x<<" "<<x<<endl;
#define ull unsigned long long
const int maxn=1e3+10;
const ull base1=13331;
const ull base2=131;
char s[maxn];
int len,c[maxn];
ull zhash1[maxn],fhash1[maxn],ipow1[maxn],zhash2[maxn],fhash2[maxn],ipow2[maxn];
vector<int>js,os;
bool check(int mid)
{
memset(c,0,sizeof(c));
for(int i=1;i<=len;i++)
if(s[i]=='A'||s[i]=='H'||s[i]=='I'||s[i]=='M'||s[i]=='O'||s[i]=='T'||s[i]=='U'||s[i]=='V'||s[i]=='W'||s[i]=='X'||s[i]=='Y')
;
else
{
c[max(1,i-mid+1)]++;
c[i+1]--;
}
for(int i=1;i<=len;i++) c[i]+=c[i-1];
for(int i=1;i<=len-mid+1;i++)
{
if(c[i]>=1) continue;
int l=i,r=i+mid-1;
if(zhash1[r]-zhash1[l-1]*ipow1[mid]==fhash1[l]-fhash1[r+1]*ipow1[mid]&&zhash2[r]-zhash2[l-1]*ipow2[mid]==fhash2[l]-fhash2[r+1]*ipow2[mid])
return true;
}
return false;
}
int main()
{
int t,ans,low,high,mid;
scanf("%d",&t);
ipow1[0]=1,ipow2[0]=1;
for(int i=1;i<=1000;i++) ipow1[i]=ipow1[i-1]*base1,ipow2[i]=ipow2[i-1]*base2;
while(t--)
{
js.clear();os.clear();
scanf("%s",s+1);
len=strlen(s+1);
for(int i=1;i<=len;i++)
if(i&1)
js.push_back(i);
else
os.push_back(i);
for(int i=1;i<=len;i++)
zhash1[i]=zhash1[i-1]*base1+s[i],zhash2[i]=zhash2[i-1]*base2+s[i];
for(int i=len;i>=1;i--)
fhash1[i]=fhash1[i+1]*base1+s[i],fhash2[i]=fhash2[i+1]*base2+s[i];
low=0,high=js.size()-1,ans=0;
while(low<=high)
{
mid=(low+high)>>1;
if(check(js[mid]))
ans=js[mid],low=mid+1;
else
high=mid-1;
}
low=0,high=os.size()-1;
while(low<=high)
{
mid=(low+high)>>1;
if(check(os[mid]))
ans=max(ans,os[mid]),low=mid+1;
else
high=mid-1;
}
printf("%d\n",ans);
}
return 0;
}