开始想的时候神游去了,发呆了好久。。。。2333,其实这题就是一个manacher+递推
想法还是很简单,但是。。。判边界真是恶心到我了。。。值得玩一玩
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
#define N 2000010
#define Mod 51123987
int n,m,p[N*2],flag1[N],flag2[N];
char S[N*2];
long long Start[N],End[N],sum[N],total,Ans;
void Manacher()
{
int x=1,m=0;
for(int i=1;i<=n;i++)
{
p[i]=1;
if(m>i)
p[i]=min(m-i,p[2*x-i]);
while(S[i-p[i]]==S[i+p[i]])
p[i]++;
total=(total+p[i]/2)%Mod;
int pos=i/2,len=p[i]-1;
flag1[pos-(len+1)/2+1]++;flag1[pos+1]--;
if(len%2==0)
{
flag2[pos]--;flag2[pos+(len+1)/2]++;
}
else
{
flag2[pos-1]--;flag2[pos+(len+1)/2-1]++;
}
if(i+p[i]-1>m)
m=i+p[i]-1,x=i;
}
}
int main()
{
scanf("%d",&n);
scanf("%s",S);
for(int i=n;i>=0;i--)
S[i*2+1]='#',S[i*2+2]=S[i];
S[0]='$';
n=n*2+1;
Manacher();
n>>=1;
long long Add=0;
for(int i=1;i<=n;i++)
{
Add=(Add+flag1[i])%Mod;
Start[i]=(Start[i]+Add)%Mod;
}
Add=0;
for(int i=n;i>=1;i--)
{
Add=(Add+flag2[i])%Mod;
End[i]=(End[i]+Add)%Mod;
}
for(int i=1;i<=n;i++)
sum[i]=(sum[i-1]+End[i])%Mod;
for(int i=1;i<=n;i++)
{
Ans=(Ans+(Start[i]*sum[i-1]%Mod))%Mod;
}
total=(total*(total-1)/2)%Mod;
Ans=((total-Ans)%Mod+Mod)%Mod;
cout<<Ans<<endl;
return 0;
}