回文树学习笔记


学习地址回文树介绍(Palindromic Tree)

一些小总结:
回文树的每个点表示一个本质不同的字符串。
有两个根,一个表示长度为0的字符串,一个表示长度为-1的字符串。
一条边意味着在两边同时添加一个字符c。
后缀链接指向后缀最长回文串。
在串S的末尾添加一个字符c,最多产生一个本质不同的回文串,只可能是现在的后缀最长回文串。
在回文树建树过程中查找后缀最长回文串以及后缀链接时指针只会向右移(添加字符只会+1),所以复杂度是O(n)的。

模板题:BZOJ3676: [Apio2014]回文串
我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最大出现值。
加入字符时在对应的回文串上cnt+1,最后自底向上传,记录cnt*len的最大值即可。

Code:

#include<bits/stdc++.h>
#define maxn 300005
#define maxc 26
using namespace std;
int n;
char s[maxn];
namespace PAM{
	int ch[maxn][maxc],fail[maxn]={1,1},len[maxn]={0,-1},last,tot=1;
	int cnt[maxn];
	void extend(int x){
		int p=last,v=s[x]-'a';
		while(s[x-len[p]-1]!=s[x]) p=fail[p];
		if(!ch[p][v]){
			int q=fail[p];len[++tot]=len[p]+2;
			while(s[x-len[q]-1]!=s[x]) q=fail[q];
			fail[tot]=ch[q][v];//q may be 1, then ch[q][v]=0, so ch[p][v] later assign.
			ch[p][v]=tot;
		}
		cnt[last=ch[p][v]]++;
	}
	void solve(){
		long long ans=0;
		for(int i=tot;i>1;i--)
			cnt[fail[i]]+=cnt[i],ans=max(ans,1ll*cnt[i]*len[i]);
		printf("%lld\n",ans);
	}
}
int main()
{
	scanf("%s",s+1),n=strlen(s+1);
	for(int i=1;i<=n;i++) PAM::extend(i);
	PAM::solve();
}

理性愉悦系列(过于硬核导致直接自闭 ):
国家集训队2017论文 《回文树及其应用》翁文涛
可持久化
硬核题目
最小回文分解

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值