点此看题面

大致题意: 每次在字符串后面加入或删除一个字符,求本质不同的子串个数。

后缀自动机

先说明,此题后缀自动机的确能过。

但我的后缀自动机比较弱,遇上一个较强的\(Hack\)数据就被卡掉了。。。(可见这场比赛的\(T1\):【HHHOJ】ZJOI2019模拟赛(十三)03.10

尽管如此,还是讲一下大致思路吧。

更新答案

考虑后缀自动机求解本质不同的子串个数时,我们需要统计\(Len_x-Len_{fa_x}\)。

所以我们可以简单定义一个\(F5\)函数来刷新答案:

#define F5(x,op) (void)(ans+=1LL*(op)*(O[x].L-O[GetFa(x)].L))

插入操作

考虑后缀自动机的插入过程,对于一个字符,我们可能会新建\(1\sim2\)个节点,且其中第一个节点需要建立于上一个字符第一个节点的基础之上,而第二个节点是作为辅助节点。

注意在插入的同时要更新\(ans\)。

由于每次插入需要上一个插入的节点信息,因此我们需要开个栈,来存储还在字符串中的字符编号。

删除操作

考虑删除,每次最多只需删除两个节点。

我们可以标记被删除的节点\(Ex=0\),存在的节点\(Ex=1\),然后记录每个节点的后继\(Nxt\),求的时候跳\(Nxt\)并路径压缩一下即可。

删除一个节点后,其所有子节点都变成了它父亲的儿子,因此要将\(Sz_{fa_x}\)先减去\(1\),再加上\(Sz_x\),即加上\(Sz_x-1\)。

更新贡献时,设这个节点为\(x\),若要减去它的贡献,就是\(F5(x,-1)\)。

但删去它之后,它所有子节点与其父节点\(L\)的差值都增加了\(Len_x-Len_{fa_x}\),也就相当于\(F5(x,Sz_x)\)。

合起来便是\(F5(x,Sz_x-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 100000
#define LL long long
using namespace std;
char s[N+5];
class SuffixAutomation//后缀自动机
{
private:
#define F5(x,op) (void)(ans+=1LL*(op)*(O[x].L-O[GetFa(x)].L))//更新答案
#define Co(x,y) (void)(++O[O[x].F=y].Sz)//连边
static const int SZ=N,C=26;int tot;LL ans;
struct SAM {int L,F,Sz,Ex,Nxt,S[C+5];}O[(SZ<<1)+5];
I int GetFa(CI x) {return O[O[x].F].Ex?O[x].F:O[x].F=GetFa(O[x].F);}//求第一个存在的父亲
I int GetNxt(int& x) {return O[x].Ex?x:x=GetNxt(O[x].Nxt);}//求出第一个存在的后继
public:
int ExSt[N+5],SamP[N+5],TwoP[N+5];//ExSt为一个记录存在节点的栈,SamP和TwoP分别存储一个字符在SAM中建的两个节点的编号
I SuffixAutomation() {O[0].Ex=O[SamP[0]=tot=1].Ex=1;}//初始化后缀自动机
I void Insert(CI x,CI id,CI lst)//插入字符
{
RI p=lst,q,k,now=SamP[id]=++tot;O[now].L=O[p].L+1,O[now].Ex=1;
W(p&&!GetNxt(O[p].S[x])) O[p].S[x]=now,p=O[p].F;
if(!p) return Co(now,1),F5(now,1);
if(O[p].L+1==O[q=O[p].S[x]].L) return Co(now,q),F5(now,1);
O[k=TwoP[id]=++tot]=O[q],O[k].L=O[p].L+1,O[k].Sz=0,O[k].Ex=1,O[k].Nxt=q,
F5(q,-1),Co(now,k),Co(q,k),F5(q,1),F5(k,1),F5(now,1);//删除原来的贡献,更新新的贡献
W(p&&!(GetNxt(O[p].S[x])^q)) O[p].S[x]=k,p=O[p].F;
}
I void Delete(CI x) {O[x].Ex=0,F5(x,O[x].Sz-1),O[GetFa(x)].Sz+=O[x].Sz-1;}//删除字符
I LL GetAns() {return ans;}//求答案
}S;
int main()
{
RI i,len,x,T=0;for(scanf("%s",s+1),len=strlen(s+1),i=1;i<=len;++i)
{
if(s[i]^'-') S.Insert(s[i]&31,i,S.SamP[S.ExSt[T]]),S.ExSt[++T]=i;//加入字符,更新栈
else//删除字符
{
S.TwoP[S.ExSt[T]]&&(S.Delete(S.TwoP[S.ExSt[T]]),0),//若插入了两个节点,则删除第二个插入的节点
S.Delete(S.SamP[S.ExSt[T]]),--T;//删除第一个插入的节点
}printf("%lld\n",S.GetAns());//输出答案
}return 0;
}

【BZOJ5084】hashit(后缀自动机水过)的更多相关文章

  1. BZOJ 5084: hashit 后缀自动机(原理题)

    比较考验对后缀自动机构建过程的理解. 之前看题解写的都是树链的并,但是想了想好像可以直接撤销,复杂度是线性的. 自己想出来的,感觉后缀自动机的题应该不太能难倒我~ 注意:一定要手画一下后缀自动机的构建 ...

  2. Match & Catch CodeForces - 427D 后缀自动机水题

    题意: 给出两个字符串a,b,求一个字符串,这个字符串是a和b的子串, 且只在a,b中出现一次,要求输出这个字符串的最小长度. 题解: 将a串放入后缀自动机中,然后记录一下每个节点对应的子串出现的次数 ...

  3. CF873F Forbidden Indices 后缀自动机+水题

    刷刷水~ Code: #include <cstdio> #include <cstring> #include <algorithm> #define N 200 ...

  4. 【bzoj2882】工艺 后缀自动机+STL-map

    题目描述 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方 ...

  5. 【bzoj5084】hashit 广义后缀自动机+树链的并+STL-set

    题目描述 你有一个字符串S,一开始为空串,要求支持两种操作 在S后面加入字母C 删除S最后一个字母 问每次操作后S有多少个两两不同的连续子串 输入 一行一个字符串Q,表示对S的操作 如果第i个字母是小 ...

  6. SAM(后缀自动机)总结

    “写sam是肯定会去写的,这样才学的了字符串,后缀数组又不会用 >ω<, sam套上数据结构的感觉就像回家一样! 里面又能剖分又能线段树合并,调试又好调,我爱死这种写法了 !qwq” SA ...

  7. 后缀自动机(SAM)

    *在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符 ...

  8. HDU 4622 多校第三场1002 后缀自动机

    比赛的时候我是用后缀数组的,但是T了. 赛后看了解题报告说,后缀数组貌似是卡你常数的时间,我算了下复杂度O(T * Q * n).这是10 ^ 8,但是考虑到每次询问的时候都要重新构造字符,所以那个n ...

  9. 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做

    题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...

随机推荐

  1. layui的表单功能

    作为一个phper还是非常喜欢这个插件的~虽然在vue的群里面说这个插件好被人怼过..废话不多说, 这次使用到的是layui的表单功能.上次的日历忘记做笔记了非常可惜,大部分其实跟着文档撸就可以,这次 ...

  2. python练习六十八:字符串练习

    题目:一个商城在搞抽奖的活动,需要在搞活动的宣传单上印刷优惠卷的验证码,验证码规定20位,生成100个 先来个简单的,20位码中只取数字 import random def num_1(num): l ...

  3. import与export

    expoer default 输出的是一个对象 export 输出的是对象的一个元素

  4. ES6和ES5中的this指向问题

    不多逼逼 直接上代码: var name = "window"; var obj = { name: 'obj', //普通函数 one: function(){ console. ...

  5. RTT设备与驱动之PIN设备

    单片机的PIN有2个基本功能:GPIO和AFIO,其中gpio的常用功能: 1 输入:上拉.下拉.模拟.浮动 2 输出:上拉.下拉.推挽.开漏 3 中断:上升沿.下降沿.双沿.高电平.低电平触发 RT ...

  6. 晶振电路的设计-AN2867学习

    一 石英晶体的等效电路.带宽: FS~FA之间就是并联带宽,越窄稳定性越好.其中Fs.Fa为Lm/Rm/Cm电抗分别为0和无穷大时的谐振频率).Fp为工作频率(通过调整负载电容CL来达到中心频率) 起 ...

  7. C# a == b ? c :d 表示的意思

    a==b 为true,这个表达式返回c; a==b为false,这个表达式返回d. 相当于: if(a == b) { return c; } else { return d; }

  8. U盘中毒问题解决

    背景: 最近在学校的打印店里打印东西,结果过了一段时间再使用的时候发现,U盘中的文件夹都成了快捷方式,只有一个pdf文件是好的,无奈,其中有比较重要的东西,所以寻求解决办法,最终解决,为方便以后查阅, ...

  9. 打开/关闭网卡无线WIFI模块

    @echo off title ------(Please run as Administrators)Please select------ :begin echo ---------------- ...

  10. hystrix应用介绍(三)

    hystrix提供了两种隔离策略:线程池隔离和信号量隔离.hystrix默认采用线程池隔离. 1.线程池隔离 不同服务通过使用不同线程池,彼此间将不受影响,达到隔离效果. 例如: 我们可以通过andT ...