一、题目
二、解法
回文自动机板题,我们先建出两个回文自动机,把每一次的 打上标记,然后再对 树内的标记求和,算出来就是这个点的回文串出现次数。然后我们在两个自动机一起跑,只需要保证经过的转移相同那么就有最后得到的回文串相同,我们把经过的两棵树的出现次数相乘在累加就是答案,注意 都要跑一遍。
时间复杂度 ,那就贴个代码吧。
#include <cstdio>
#include <cstring>
const int M = 50005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n;char s[M];long long ans;
struct node
{
int fail,len,ch[26];
node() {memset(ch,0,sizeof ch);fail=len=0;}
};
struct Pam
{
node b[M];int n,last,cnt,f[M];
Pam()
{
b[0].fail=1;b[1].len=-1;
cnt=1;
}
int get_fail(int x)
{
while(s[n-b[x].len-1]^s[n])
x=b[x].fail;
return x;
}
void ins()
{
n++;
int p=get_fail(last),c=s[n]-'A';
if(!b[p].ch[c])
{
b[++cnt].len=b[p].len+2;
int tmp=get_fail(b[p].fail);
b[cnt].fail=b[tmp].ch[c];
b[p].ch[c]=cnt;
}
last=b[p].ch[c];
f[last]++;
}
void sol()
{
for(int i=cnt;i;i--) f[b[i].fail]+=f[i];
}
}A,B;
void dfs(int x,int y)
{
if(x+y>2) ans+=1ll*A.f[x]*B.f[y];
for(int i=0;i<26;i++)
if(A.b[x].ch[i] && B.b[y].ch[i])
dfs(A.b[x].ch[i],B.b[y].ch[i]);
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++) A.ins();
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++) B.ins();
A.sol();B.sol();
dfs(1,1);dfs(0,0);
printf("%lld\n",ans);
}