把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【BZOJ4480】 [JSOI2013] 快乐的jyy(回文自动机裸题)

点此看题面

大致题意: 给定两个字符串,问有多少对子串满足二者是相同的回文串。

回文自动机

感觉是一道比较裸的题目。

直接建出两个串的回文自动机,然后倒序枚举节点,统计\(C\)(子树大小)的同时求出\(\sum C[0]\times 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\n",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;
}
posted @ 2020-07-21 19:07  TheLostWeak  阅读(123)  评论(0编辑  收藏  举报