Luogu P3804 后缀自动机模板

该博客详细介绍了如何解决Luogu P3804问题,通过利用后缀自动机来计算字符串中各个子串的出现次数。文章强调在构建过程中,新节点的计数初始化以及克隆节点处理的重要性,并解释了为何克隆节点的计数应设为0。此外,博主还分享了关于后缀自动机中节点计数的有趣性质。
摘要由CSDN通过智能技术生成

luoguP3804 后缀自动机
这个题转化一下就是求每个子串的出现次数,也就是endpos集合的大小。

参考oiwiki中的应用——出现次数

就是新建节点时初始化cnt为1,clone时初始化cnt为0.

然后长度排序,在link树中从叶子更新到根节点,就统计完了。

这里主要解释一下为什么clone的点是赋值为0,非clone点赋值为1.

首先,非clone点可以肯定它第一次出现,所以把它赋值为1,这个应该可以理解,那么clone点为什么就初始化为0?

因为对于一个点,分裂的前提是len[p]+1 != len[q]

也就是说,一个点分裂成了两个endpos集合。在一棵link树中,一个节点的endpos集合被它的儿子平分了,所以被clone的点,它应该由它的子树更新而来,它本身不需要初始化,因为初始化之后,结果会变大。

实际上,我们初始化为1的点就是插入s的顺序的那些点,也就是说,按照插入顺序,依次经过的每个点它在后缀链接树上是叶子节点。

这个性质挺有趣的。
在这里插入图片描述
代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<ctime>
#define up(i,x,y) for(int i = x;i <= y;i ++)
#define down(i,x,y) for(int i = x;i >= y;i --)
#define mem(a,b) memset((a),(b),sizeof(a))
#define mod(x) ((x)%MOD)
#define lson p<<1
#define rson p<<1|1
using namespace std;
typedef long long ll;
const int SIZE = 2000010;
const int INF = 2147483640;
const double eps = 1e-8;

inline void RD(int &x)
{
   
    x = 0;  char c; c = getchar();
    bool flag = 0;
    if(c == '-')    flag = 1;
    while(c < '0' || c > '9')   {
   if(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值