说白了就是判断两个相反的串,从某一位置开始,向两个串的相反方向延伸,使得到的子串是相同的,并且长度最大。求最大的延伸长度。
水题,很明显的hash吧,O(nlgn)。
也可以看作是manacher的变种,跑manacher可以做到线性复杂度。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MOD=(1e9)+7;
char ch;
int a[500005],b[500005],p[500005];
int hasha[500005],hashb[500005],n,i,l,r,mid,len;
long long ans;
int main(){
scanf("%d\n",&n);
for (i=1;i<=n;i++){
ch=getchar();
a[i]=ch-'0';
b[i]=a[i]^1;
}
for (i=1,p[0]=1;i<=n;i++) p[i]=p[i-1]*MOD;
for (i=1;i<=n;i++)
hasha[i]=hasha[i-1]*MOD+a[i];
for (i=n;i>0;i--)
hashb[i]=hashb[i+1]*MOD+b[i];
for (i=1;i<n;i++){
l=1; r=min(i,n-i); len=0;
while (l<=r){
mid=(l+r)>>1;
if (hasha[i]-hasha[i-mid]*p[mid]==hashb[i+1]-hashb[i+mid+1]*p[mid])
len=mid, l=mid+1;
else r=mid-1;
}
ans+=(long long)len;
}
printf("%I64d\n",ans);
return 0;
}