此题有95分暴力。。。
发现AABB的统计相当于对AA的统计。于是可以计算出每个点左侧为AA的方案数。枚举|A|,将字符串分成长度为|A|的小段,当AA中点在小段中的情况可以利用SA+rmq,O(1)求。于是就能在O(n/1+n/2+...+n/n)=O(nlogn)内求解。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 80005
using namespace std;
int n,T,A[N],B[N],lg[N],bit[20];long long Ans;
struct SuffixArray
{
char a[N];
int SA[N],Rk[N],Ht[N],X[N],Y[N],v[N],Min[N][20];
void GetSA(int n,int m=256)
{
int *x=X,*y=Y,i,p,j;
memset(v,0,sizeof v);
for(i=1;i<=n;i++)v[x[i]=a[i]]++;
for(i=1;i<=m;i++)v[i]+=v[i-1];
for(i=n;i>=1;i--)SA[v[x[i]]--]=i;
for(i=1;i<=n;i<<=1,m=p)
{
p=0;
memset(v,0,sizeof v);
for(j=n-i+1;j<=n;j++)y[++p]=j;
for(j=1;j<=n;j++)if(SA[j]>i)y[++p]=SA[j]-i;
for(j=1;j<=n;j++)v[x[y[j]]]++;
for(j=1;j<=m;j++)v[j]+=v[j-1];
for(j=n;j>=1;j--)SA[v[x[y[j]]]--]=y[j];
swap(x,y);
p=1;x[SA[1]]=1;
for(j=2;j<=n;j++)
if(y[SA[j-1]]==y[SA[j]]&&y[SA[j-1]+i]==y[SA[j]+i]) x[SA[j]]=p;
else x[SA[j]]=++p;
if(p>=n)break;
}
}
void GetHt(int n)
{
int k=0;
for(int i=1;i<=n;i++)Rk[SA[i]]=i;
for(int i=1;i<=n;i++)
{
if(k)k--;
int j=SA[Rk[i]-1];
while(i+k<=n&&j+k<=n&&a[i+k]==a[j+k])k++;
Ht[Rk[i]]=k;
}
}
void Get(int n)
{
memset(SA,0,sizeof SA);
memset(Ht,0,sizeof Ht);
memset(Rk,0,sizeof Rk);
memset(X,0,sizeof X);
memset(Y,0,sizeof Y);
memset(Min,0,sizeof Min);
GetSA(n);GetHt(n);
for (int i=1;i<=n;i++)
Min[i][0]=Ht[i];
for (int i=1;i<=15;i++)
for (int j=1;j<=n;j++)
Min[j][i]=min(Min[j][i-1],Min[j+bit[i-1]][i-1]);
}
int lcp(int x,int y)
{
if (Rk[x]>Rk[y]) swap(x,y);
x=Rk[x];y=Rk[y];
int t=lg[y-x];
return min(Min[x+1][t],Min[y-bit[t]+1][t]);
}
}S1,S2;
int main()
{
bit[0]=1;
for (int i=1;i<=15;i++) bit[i]=bit[i-1]<<1;
for (int i=0,j=1,next=2;i<=15;i++,next<<=1)
for (;j<=next;j++) lg[j]=i;
scanf("%d",&T);
while(T--)
{
Ans=0;
memset(A,0,sizeof A);
memset(B,0,sizeof B);
scanf("%s",S1.a+1);n=strlen(S1.a+1);
for (int i=1;i<=n;i++) S2.a[n-i+1]=S1.a[i];
S1.Get(n);
S2.Get(n);
for (int i=1;i<=n/2;i++)
{
for (int j=1;j+i<=n;j+=i)
{
int x=S1.lcp(j,j+i),y=S2.lcp(n-j+1,n-j-i+1);
int l=max(j,j-y+i),r=min(j+i,j+x)-1;
if (l<=r)
{
A[l+i]++;A[r+i+1]--;
B[l-i]++;B[r-i+1]--;
}
}
}
for (int i=1;i<=n;i++)
A[i]+=A[i-1],B[i]+=B[i-1];
for (int i=1;i<=n;i++)
Ans+=A[i]*B[i];
printf("%lld\n",Ans);
}
}