题意
分析
考虑两个串如果反过来不相同个数怎么统计
其实就是正串和反串都放在一个广义后缀自动机上统计,然后 答案/2
这样对吗?我们考虑自己本身回文的情况,还要加上本质不同的回文串个数
直接上回文自动机就可以了
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 800010;
char s[N];
struct Sam
{
ll fail[N],step[N],g[N][27],last,tot;
void init()
{
memset(fail,0,sizeof(fail));
memset(step,0,sizeof(step));
memset(g,0,sizeof(g));
last = tot = 1;
}
void ins(ll nx)
{
if(g[last][nx])
{
ll p = last; ll q = g[last][nx];
if(step[q] == step[p] +1) last = q;
else
{
ll nq = ++tot; step[nq] = step[p] + 1;
fail[nq] = fail[q]; fail[q] = nq;
for(ll i=1;i<=26;i++) g[nq][i] = g[q][i];
while(g[p][nx] == q && p){g[p][nx] = nq,p=fail[p];} last = nq;
}return ;
}
ll p = last; ll np = ++tot; step[np] = step[p] + 1;
while(!g[p][nx] && p) g[p][nx] = np,p=fail[p];
if(!p) fail[np] = 1;
else
{
ll q = g[p][nx];
if(step[q] == step[p]+1){fail[np] = q;}
else
{
ll nq = ++tot; step[nq] = step[p] + 1;
fail[nq] = fail[q]; fail[np] = fail[q] = nq;
for(ll i=1;i<=26;i++) g[nq][i] = g[q][i];
while(g[p][nx] == q && p) g[p][nx] = nq,p=fail[p];
}
}last=np;
}
}SAM;
struct Pam
{
ll fail[N],step[N],g[N][27],last,n,tot;
void init()
{
memset(step,0,sizeof(step));
memset(g,0,sizeof(g));
fail[0] = fail[1] = 1; step[1] = -1; tot = 1;
}
void ins(ll nx)
{
ll p = last; n++;
while(s[n] != s[n-step[p]-1]) p = fail[p];
if(!g[p][nx])
{
ll np = ++tot; step[np] = step[p] + 2;
ll q = fail[p];
while(s[n] != s[n-step[q]-1]) q = fail[q];
fail[np] = g[q][nx]; g[p][nx] = np;
}last = g[p][nx];
}
}PAM;
int main()
{
scanf("%s",s+1); ll len=strlen(s+1); SAM.init(); PAM.init();
for(ll i=1;i<=len;i++)
{
SAM.ins(s[i]-'a'+1);
PAM.ins(s[i]-'a'+1);
}
SAM.last = 1; for(ll i=len;i>=1;i--) SAM.ins(s[i]-'a'+1);
ll ans = PAM.tot-1;
for(ll i=1;i<=SAM.tot;i++) ans += SAM.step[i] - SAM.step[SAM.fail[i]];
return printf("%lld\n",ans>>1),0;
}