大致题意: 给定两个字符串,问有多少对子串满足二者是相同的回文串。
回文自动机
感觉是一道比较裸的题目。
直接建出两个串的回文自动机,然后倒序枚举节点,统计(C)(子树大小)的同时求出(sum C[0] imes C[1])即为答案
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 50000
using namespace std;
int n;char s[N+5];
class PalindromeAutomation//回文自动机
{
private:
int Nt,lst;struct node {int L,C[2],F,S[30];}O[2*N+5];
I int Fail(RI x,CI id) {W(s[id-O[x].L-1]^s[id]) x=O[x].F;return x;}
public:
I PalindromeAutomation() {O[O[0].F=Nt=1].L=-1;}I void Init() {lst=0;}
I void Ins(CI id,CI op)//插入元素
{
RI x=s[id]&31,t=Fail(lst,id),o;!O[t].S[x]&&(o=++Nt,
O[o].L=O[t].L+2,O[o].F=O[Fail(O[t].F,id)].S[x],O[t].S[x]=o);
++O[lst=O[t].S[x]].C[op];//C统计出现次数
}
I void Work()//求答案
{
RI i;long long t=0;for(i=Nt;i^1;--i)//倒序枚举
t+=1LL*O[i].C[0]*O[i].C[1],O[O[i].F].C[0]+=O[i].C[0],O[O[i].F].C[1]+=O[i].C[1];//统计答案,上传信息
printf("%lld
",t);
}
}P;
int main()
{
RI i;for(scanf("%s",s+1),n=strlen(s+1),P.Init(),i=1;i<=n;++i) P.Ins(i,0);
for(scanf("%s",s+1),n=strlen(s+1),P.Init(),i=1;i<=n;++i) P.Ins(i,1);return P.Work(),0;
}