目录:
题目:
分析:
一个反对称串就是将这个串取反然后放在原串后面的话是回文串,然后回文串是满足单调性的(如果以一个点为中心扩展 k k 格是回文串,那么扩展格也是回文串),所以我们可以枚举中心,然后二分最大的 k k ,然后用判断回文。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#define LL long long
#define ull unsigned long long
using namespace std;
const ull bace=2000001001;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
ull king[500001],h[500001],hr[500001];
int min(int x,int y)
{
return x<y? x:y;
}
int max(int x,int y)
{
return x>y? x:y;
}
bool check(int l,int r,int x)
{
ull s1,s2;
s1=h[l+x-1]-h[l-1];
s2=hr[r+x-1]-hr[r-1];
if(l>r) swap(l,r),swap(s1,s2);
s1*=king[r-l];
return s1==s2;
}
int main()
{
int n=read();
char s[500001];
scanf("%s",&s);
king[0]=1;
for(int i=1;i<=n;i++) king[i]=king[i-1]*bace;
for(int i=1;i<=n;i++)
h[i]=h[i-1]+s[i-1]*king[i];
for(int i=1;i<=n/2;i++) swap(s[i-1],s[n-i]);
for(int i=1;i<=n;i++)
if(s[i-1]=='0') s[i-1]='1';
else s[i-1]='0';
for(int i=1;i<=n;i++)
hr[i]=hr[i-1]+s[i-1]*king[i];
long long ans=0;
for(int i=2;i<=n;i++)
{
int l=1,r=min(n-i+1,i-1);
int maxn=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(i,n-i+2,mid)) maxn=max(maxn,mid),l=mid+1;
else r=mid-1;
}
ans+=maxn;
}
printf("%lld",ans);
return 0;
}