题目链接

\(Description\)

给你一个字符串init,要求支持两个操作:
(1)在当前字符串的后面插入一个字符串s
(2)询问字符串s在当前字符串中出现了几次(作为连续子串)
强制在线。

\(Solution\)

对于每次询问,串\(s\)出现的次数就是\(s\)在SAM上走完后到达节点的\(|right|\)(SAM上是模板串的所有子串的状态啊 没有转移那就是匹配不上了)。
于是就成了动态维护\(right\)集合的大小。
暴力的话,每次加入一个字符 只需要沿着\(fa\)向上++\(|right|\)就可以了。要注意复制节点\(nq\)的时候\(|right|\)也要复制。
现在需要用LCT来动态维护parent树,并支持更新点到根这条链的值,连边删边。询问的时候直接输出到达节点的size即可。

这棵树是有根树,所以不需要Make_root()
别忘了\(sz\)维护的是到叶节点的size(注意\(sz\)的更新);改变SAM中的\(fa\)时都要修改parent树。
对于\(sz\)初值:\(sz[np]=1\),\(sz[nq]=0\)。想想以前不就是这样吗,只对每个\(np\)走到的初始化为\(1\).

//163128kb  16108ms
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=(6e5+5)*2;namespace LCT
{#define lson son[x][0]#define rson son[x][1]int fa[N],son[N][2],sz[N],tag[N],sk[N];inline void Update(int x,int v){sz[x]+=v, tag[x]+=v;}inline void PushDown(int x){if(tag[x]) Update(lson,tag[x]), Update(rson,tag[x]), tag[x]=0;}inline bool n_root(int x){return son[fa[x]][0]==x||son[fa[x]][1]==x;}void Rotate(int x){int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;if(n_root(a)) son[b][son[b][1]==a]=x;if(son[x][r]) fa[son[x][r]]=a;fa[x]=b, fa[a]=x, son[a][l]=son[x][r], son[x][r]=a;}void Splay(int x){int a=x,t=1; sk[1]=x;while(n_root(a)) sk[++t]=a=fa[a];while(t) PushDown(sk[t--]);while(n_root(x)){if(n_root(a=fa[x])) Rotate(son[a][1]==x^son[fa[a]][1]==a?x:a);Rotate(x);}}void Access(int x){for(int pre=0; x; x=fa[pre=x])Splay(x), rson=pre;//, Update(x);}void Link(int x,int y){//Link x->yAccess(y), Splay(y), fa[x]=y, Update(y,sz[x]);}void Cut(int x){//Cut x->fa[x]Access(x), Splay(x), Update(lson,-sz[x]), lson=fa[lson]=0;//Update()!}
}
struct Suffix_Automaton
{int l,tot,las,Mask,fa[N],son[N][26],len[N];char s[3000005];void Insert(int c){int p=las,np=++tot;len[las=np]=len[p]+1, LCT::sz[np]=1;for(; p&&!son[p][c]; p=fa[p]) son[p][c]=np;if(!p) fa[np]=1, LCT::Link(np,1);else{int q=son[p][c];if(len[q]==len[p]+1) fa[np]=q, LCT::Link(np,q);else{int nq=++tot; len[nq]=len[p]+1;memcpy(son[nq],son[q],sizeof son[q]);fa[nq]=fa[q], LCT::Link(nq,fa[q]);fa[np]=fa[q]=nq, LCT::Cut(q), LCT::Link(np,nq), LCT::Link(q,nq);for(; son[p][c]==q; p=fa[p]) son[p][c]=nq;}}}inline void Decode_With_Mask(int mask)//mask是传参 {for(int i=0; i<l; ++i)mask=(mask*131+i)%l, std::swap(s[i+1],s[mask+1]);}void Init(){tot=las=1, Mask=0;scanf("%s",s+1), l=strlen(s+1);for(int i=1; i<=l; ++i) Insert(s[i]-'A');}void Build(){scanf("%s",s+1), l=strlen(s+1);Decode_With_Mask(Mask);for(int i=1; i<=l; ++i) Insert(s[i]-'A');}int Walk(){int p=1;for(int i=1; i<=l; ++i)if(!(p=son[p][s[i]-'A'])) return 0;LCT::Splay(p);return Mask^=LCT::sz[p], LCT::sz[p];}void Query(){scanf("%s",s+1), l=strlen(s+1);Decode_With_Mask(Mask);printf("%d\n",Walk());}
}sam;int main()
{int Q; char opt[8];scanf("%d",&Q), sam.Init();while(Q--){if(scanf("%s",opt),opt[0]=='A') sam.Build();else sam.Query();}return 0;
}

转载于:https://www.cnblogs.com/SovietPower/p/9239427.html

BZOJ.2555.SubString(后缀自动机 LCT)相关推荐

  1. BZOJ 2555: SubString [后缀自动机 LCT]

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MB Submit: 2045  Solved: 583 [Submit][Status][ ...

  2. HDU多校4 - 6988 Display Substring(后缀自动机+二分)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的字符串 sss,每个字母都有一个权值,现在要求所有本质不同子串中权值和第 kkk 大的权值 题目分析:如果没有本质不同,那有一个很简单的二分套二 ...

  3. BZOJ 3238 差异 [后缀自动机]

    题目 一个长度为n的字符串S,令TiT_i表示它从第i个字符开始的后缀.求 ∑1≤i<j≤nlen(Ti)+len(Tj)−2∗lcp(Ti,Tj) \sum_{1\le i 其中len(a)表 ...

  4. 【BZOJ4545】DQS的trie 后缀自动机+LCT

    [BZOJ4545]DQS的trie Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符 ...

  5. [BZOJ 2555] SubString

    Substring 题意 题面 给定一个初始字符串, 要求支持在这个字符串后添加字符串/查询某个字符串作为子串的出现次数. 强制在线. 长度 \(\le600000\),询问次数 \(\le10000 ...

  6. [bzoj 2555]Substring

    传送门 Description 给你一个字符串\(init\),要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线 ...

  7. 「雅礼集训 2017 Day7」事情的相似度(后缀自动机+LCT+树状数组)

    description 点击查看题目内容 solution Step1 无脑建SAMSAMSAM 两个前缀的最长公共后缀就是parent−treeparent-treeparent−tree上两点的l ...

  8. SPOJ - LCS Longest Common Substring(后缀自动机)

    题目链接:点击查看 题目大意:给出两个字符串,求出其最长公共子串的长度 题目分析:可以对第一个字符串建立SAM,然后令第二个字符串在建好的SAM上跑就好了,如果遇到不能跑的点,就往上折返直到找到可以继 ...

  9. UOJ #395 BZOJ 5417 Luogu P4770 [NOI2018]你的名字 (后缀自动机、线段树合并)

    NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) http ...

最新文章

  1. spring (由Rod Johnson创建的一个开源框架)
  2. 三个简单工厂实例 - C++实现
  3. 基于VC++的GDI常用坐标系统及应用
  4. python两数相加取_Leetcode_两数相加_Python
  5. GC回收垃圾对象过程
  6. python面向对象三大特性、类的约束、print带颜色输出及super补充
  7. 计算机配置界面在那,在哪里设置关机画面?设置为原来的经典界面?
  8. 高级产品经理的思维方式
  9. Kinect开发学习笔记之(三)Kinect开发环境配置
  10. 网站后台目录扫描工具Dirbuster和御剑(脚本小子的最爱)
  11. 2021-07-21
  12. Linux Shell发邮件笔记
  13. 8 款浏览器兼容性测试工具介绍,需要的赶紧收藏吧!
  14. centos7 firewall-cmd 命令报错 ModuleNotFoundError: No module named 'gi'
  15. html th中加斜杠,vue element 表头添加斜线
  16. 你的计划为什么执行不下去 怎么破
  17. Oracle中merge into的使用方法
  18. opera创建房间—比较详细
  19. linux串口卡驱动下载,ch350l驱动
  20. 网络爬虫与信息提取--正则表达式---淘宝商品比价定向爬虫

热门文章

  1. python map lambda 分割字符串_[转] Python特殊语法:filter、map、reduce、lambda
  2. Intellij IDLE 中javafx使用与配置
  3. 为什么有人说:“离职见人品”?
  4. 失眠患者应该边工作边调理,还是辞职回家调理?
  5. 鱼腥草可以随便吃吗?
  6. 了解普通人的心理,在销售中非常重要
  7. 2K分辨率下1070TI更换2080S能有多大提升,值得换吗?
  8. 区块链优秀github开源项目
  9. 了解一点儿JavaConfig
  10. Dubbo-Admin 2.7 本地安装和部署