后缀自动机SAM
zxyoi_dreamer
退役了退役了爬了爬了,搞个锤子算法竞赛,不如好好享受大学生活。
展开
-
【校内模拟】string (SAM)(DSU on tree)
简要题意:给一个串,询问有多少个区间可以由某一个串重复 kkk 次得到。题解:首先很容易发现就是询问有多少个子串有 n/kn/kn/k 的循环节。也就是说要有 n−n/kn-n/kn−n/k 的 border。也就是求由多少对 l,rl,rl,r,满足 lcs(l,r)≥(r−l)⋅(k−1)lcs(l,r)\ge (r-l)\cdot(k-1)lcs(l,r)≥(r−l)⋅(k−1)...原创 2020-02-29 16:09:05 · 262 阅读 · 0 评论 -
【CTSC2012】熟悉的文章(广义SAM)(二分答案)(单调队列优化DP)
传送门题解:这个问题看上去就很二分答案。建立广义SAM,然后把询问串放上去跑,处理出每个点向前最多长度为多少的串能够产生匹配。然后现在二分答案,对于二分的LLL,我们需要处理出最多有多少字符可以在广义SAM里面匹配。考虑dp,设dp[i]dp[i]dp[i]表示以iii结尾的串之前能够有多少字符在广义SAM里面匹配。转移是一个区间最大值,直接上单调队列即可。代码:#includ...原创 2019-09-24 18:00:49 · 151 阅读 · 0 评论 -
【LOJ6041】「雅礼集训 2017 Day7」事情的相似度(SAM)(LCT)(树状数组)
传送门题面太暴力了题解:两个前缀的LCS就是SAM的fail树上的LCA。将询问按照rrr排序。暴力处理询问的方式就是跳fail树看有没有之前打上的标记。然后求一个后缀最大值。利用LCT的access来进行打标记,在切换儿子的时候将最大值扔到树状数组里面即可。代码:#include<bits/stdc++.h>#define ll long long#define...原创 2019-09-24 19:39:01 · 195 阅读 · 0 评论 -
【BZOJ2780】Sevenk Love Oimaster(广义SAM)(set启发式合并)
传送门题解:显然是一个裸的广义SAM。问题在于求right集合的大小。我们知道广义SAM求right集合大小可以在建立完广义SAM后暴跳fail更新,也可以直接用set启发式合并。随便写写就好了,这种东西就是怎么开心怎么玩。代码:#include<bits/stdc++.h>#define ll long long#define re register#defin...原创 2019-09-24 20:24:45 · 167 阅读 · 0 评论 -
【NOI2018】你的名字(SAM)(线段树合并)
传送门题解:反正空间有1.22个G,xjb乱开也不会MLE题意简述:给你一个串 SSS,每次询问给出串 TTT 和区间 l,rl,rl,r,请你回答TTT有多少个本质不同的子串没有在 S[l:r]S[l:r]S[l:r] 中出现。我们如果能够求出 TTT 每个前缀在 S[l:r]S[l:r]S[l:r] 中的最长匹配长度问题就解决了。首先考虑 l=1,r=∣S∣l=1,r=|S|l=...原创 2019-09-26 19:20:24 · 201 阅读 · 0 评论 -
【校内模拟】子串(SAM)(LCT)(主席树)
题解:最后实现注意一下字符串边界,LCT稍微考虑一下可以不用写cut。代码:#include<bits/stdc++.h>#define ll long long#define re register#define cs constnamespace IO{ cs int Rlen=1<<22|1; char buf[Rlen],*p1,*p2; i...原创 2019-09-30 21:15:12 · 289 阅读 · 0 评论 -
【洛谷P4081】[USACO17DEC]Standing Out from the Herd(广义SAM)
传送门题解:比较套路的题,建广义SAM然后暴跳fail更新所属串集合。所属串集合大小为1的保留那个元素,否则存为-1。最后直接把答案加到对应串上即可。代码:#include<bits/stdc++.h>#define ll long long#define re register#define cs constcs int N=1e5+7;int n;ch...原创 2019-10-06 09:05:31 · 130 阅读 · 0 评论 -
【BZOJ2555】SubString(SAM)(LCT)
传送门题解:仔细想一想发现我们需要维护rightrightright集合的大小,也就是failfailfail树的子树大小由于强制在线,随便用LCT维护一下子树sizsizsiz即可。代码:#include<bits/stdc++.h>#define ll long long#define re register#define cs constnamespace...原创 2019-10-06 14:55:43 · 131 阅读 · 0 评论 -
【CF666E】Forensic Examination(广义SAM)(线段树合并)(树上倍增)
传送门题解:首先建立广义SAM,求匹配位置直接 failfailfail 树上倍增即可。至于匹配次数,直接对于所有nnn个串来一个线段树合并即可。然后就没了。。。非常套路,没什么细节。代码:#include<bits/stdc++.h>#define ll long long#define re register #define cs constnamespa...原创 2019-10-06 16:25:48 · 176 阅读 · 0 评论 -
【SCOI2012】喵星球上的点名(SAM)(树上差分)
传送门原题数据过水导致一个log跑不过根号目前知道两种根号做法,暴跳SAM的根号做法和本身就是根号的莫队做法,如果要卡的话这两种是绝对不可能比log快的。来加一个强制在线题解:首先用map存转移把广义SAM建出来。我们注意到第一个询问就是问终点的fail树内部有多少个不同的串。直接树上差分打标记解决。第二个询问就是问它的所有匹配点在fail树上到根的链的并集上有多少个之前的询问的终...原创 2019-10-08 10:55:57 · 165 阅读 · 0 评论 -
【洛谷P4482】[BJWC2018]Border 的四种求法(SAM)(线段树)(链分治)
传送门题解:思博题一写就是一下午。。。首先区间border这个玩意是没有办法直接做的。我还没有听说过有什么字符串理论是针对区间border的,我目前知道所有字符串border理论全部是针对全串的,如果您知道区间border的相关理论,欢迎打脸告知博主。那么实际上转化成字符串术语,我们询问的是满足i−l+1≤lcs(i,r),l≤i<ri-l+1\leq lcs(i,r),l\le...原创 2019-10-08 16:18:08 · 322 阅读 · 0 评论 -
【CF1037H】Security(贪心)(SAM)(线段树)
传送门题解:和 NOI2018 你的名字 是一个套路。首先我们求出ttt在sss中的匹配位置。然后贪心考虑尽可能让答案前缀和TTT相同。也就是说我们要在某个匹配后面接一个比TTT当前位置大的字符,然后看能不能在[l,r][l,r][l,r]中匹配上。线段树合并维护一下right集合。然后看能否匹配直接看right集合在这个区间是否为空即可。代码:#include<bits/...原创 2019-10-08 18:56:30 · 168 阅读 · 0 评论 -
【BZOJ5084】hashit(广义SAM)(DFS序)(树上差分)
传送门题解:这个做法在离线情况下可以做到O(26n+nlogn)O(26n+n\log n)O(26n+nlogn),强制在线可能会被卡成O(nn)O(n\sqrt n)O(nn),但是由于不用哈希,常数会比后缀平衡树做法小一点。首先建立广义SAM,那么某个时刻的答案实际上就是此时所有串在SAM上的节点到根节点的链的并,直接利用DFS序树上差分算一下答案即可。代码:#includ...原创 2019-10-10 09:53:45 · 202 阅读 · 0 评论 -
【CTSC2010】珠宝商(SAM)(点分治)(根号分治)
传送门给你一棵树,树上每个点有字符,询问所有树上路径形成的字符串在给定模式串中一共出现了几次。在模式串中不同位置出现要多次计算。题解:好题啊。树上路径统计类的问题显然考虑的一般就是链分治和点分治。而这种路径形成字符串的东西显然不是链分治可以搞的。考虑点分治,假设当前分治中心为uuu,则我们需要考虑v→u→wv\rightarrow u\rightarrow wv→u→w的路径。我们...原创 2019-10-10 14:38:55 · 262 阅读 · 0 评论 -
【CF700E】Cool Slogans(SAM)(线段树合并)(DP)
传送门洛谷上面那个翻译简直有毒,不知所云,最好自己去读英文题面。题意简述如下:给你一个字符串SSS,请你构造一个字符串序列s1,s2⋯ ,sks_1,s_2\cdots ,s_ks1,s2⋯,sk,使得∀i,si\forall i,s_i∀i,si是SSS的子串,且sis_isi在si−1s_{i-1}si−1中出现了至少两次,请问你最大化kkk,即序列长度。题解:我们只考...原创 2019-09-24 16:45:42 · 150 阅读 · 0 评论 -
【BZOJ3413】匹配(SAM)(线段树合并)
传送门这道题的题意没有歧义,但是说得不是很清楚。简要叙述如下:给你一个母串SSS,每次给一个串TTT。现在要寻找TTT在SSS中出现的位置,枚举匹配位置在SSS中的开头1→∣S∣1\rightarrow|S|1→∣S∣,然后从TTT中一位一位进行匹配,如果失配跳到下一个开头继续匹配,如果∣T∣|T|∣T∣完全匹配,则停止,如果所有开头位置都枚举过了,也停止,问进行字符比较的次数。题解:对...原创 2019-09-24 15:49:08 · 239 阅读 · 0 评论 -
【HEOI2016】【TJOI2016】字符串(SAM)(线段树合并)(树上倍增)
传送门题解:询问的是[a,b][a,b][a,b]的所有子串和[c,d][c,d][c,d]整个串的LCP。翻转一下变成LCS。由于是对于[c,d]整个串,我们二分答案之后树上倍增找到对应节点,看一下SAM这个点上right集合里面有没有我们要的[a,b-len+1]的串就行了。求right集合需要线段树合并。代码:#include<bits/stdc++.h>#de...原创 2019-09-24 09:47:18 · 278 阅读 · 0 评论 -
2018.12.15【SPOJ-LCS】Longest Common Substring(后缀自动机SAM)
传送门解析:小声BB:vjudge上面应该出了一点问题,C++会Language Erro,C++14就没有问题。思路:建立其中一个串的SAM,然后拿另外一个串去匹配,能够匹配到的最大长度就是最长公共子串。啊你问我为什么这样是对的,请回去重新学习什么是有限状态自动机。能搞明白FSM的应该都不会问这种问题。代码:#include<bits/stdc++.h>usin...原创 2018-12-15 15:52:54 · 143 阅读 · 0 评论 -
2018.12.15【SPOJ-LCS2】Longest Common Substring II(后缀自动机SAM)
传送门解析:这道题可以把所有串接在一起构建后缀自动机来做,但是那样还不如写后缀数组。。。所以这里提供一个只有后缀自动机能实现的做法。思路:首先构建出第一个串的后缀自动机。然后拿其他的串放到后缀自动机上面跑。同时更新答案。代码里面的lll记录的是该串在该状态下能够与前面所有串产生的最大交集,lenlenlen记录的是前面所有串在该状态下能够产生的最大交集。跑的时候记录一下目前匹配了...原创 2018-12-15 16:56:18 · 167 阅读 · 0 评论 -
2018.12.22【TJOI2015】【BZOJ3998】【洛谷P3975】弦论(SAM)
BZOJ传送门洛谷传送门解析:在本校OJ上又递归爆栈空间了。。。不过手动汇编开栈后是OJ上跑的最快的。。。思路:对于只考虑本质不同的字串的情况,就是SAM上跳一个fail链统计一下本质不同字串个数,然后一个节点的本质不同字串总和就是它DAG上所有后继状态的本质不同字串数之和,当然还要考虑它自己的cnt。不过为了过会的字串查找,需要单独统计当前状态所有后继之和。即我们需要把cnt留着。...原创 2018-12-22 11:50:06 · 1236 阅读 · 0 评论 -
2019.01.01【ZJOI2015】【BZOJ3629】【洛谷P3346】诸神眷顾的幻想乡(广义SAM)
BZOJ传送门洛谷传送门解析:裸的广义SAM,其实广义SAM在构建的时候与SAM的差别就是需要传递一个原来的父亲节点编号,其他就没什么了。这道题要统计不同的字串个数,直接每个节点lenu−lenfaulen_u-len_{fa_u}lenu−lenfau就是这个节点对于它的父亲产生的新的子串个数,然后。。。就没有然后了。。。代码:#include<bits/stdc++...原创 2019-01-01 18:54:14 · 190 阅读 · 0 评论 -
2019.02.22【TJOI2018】【BZOJ5337】【洛谷P4591】碱基序列 str(SAM)(滚动数组DP)
BZOJ传送门洛谷传送门解析:这道题。。。怎么说呢。。。真是水出了新高度,但是需要熟练掌握SAM。首先对原串建出SAM。显然,匹配到一个位置后的endpos集合就是所有匹配位置,endpos集合的大小就是匹配次数。所以我们只需要计算匹配到每个位置的方案数就行了。枚举当前集合的所有串,枚举所有已经匹配上一个集合的状态,在原状态上进行后续转移。注意失配的情况直接放弃。由于只会用到匹...原创 2019-02-22 13:22:11 · 281 阅读 · 0 评论 -
2019.02.22【HAOI2016】【BZOJ4566】【洛谷P3181】找相同字符(SAM)
BZOJ传送门洛谷传送门解析:这种题显然就是建立一个SAM,拿另一个上去跑。代码:#include&lt;bits/stdc++.h&gt;using namespace std;#define ll long long#define re register#define gc get_char#define cs constcs int N=200005; name...原创 2019-02-22 23:43:50 · 141 阅读 · 0 评论 -
2019.02.28【HAOI2018】【BZOJ5302】【洛谷P4493】字串覆盖(后缀自动机SAM)(线段树合并)(倍增法)
BZOJ传送门洛谷传送门解析:乍一看十分毒瘤,仿佛不可做。仔细分析,其实是有点门道的。其实贪心可以发现,就是让PPP的子串尽可能在TTT上匹配,且尽可能向前匹配,而且匹配还不能相交。。。。匹配匹配多次匹配显然就是需要维护right集合的,好的上线段树合并。我们先建立对AAA建立后缀自动机,然后将BBB放上去跑匹配。显然这时候每一个点匹配的位置都是前缀匹配的位置,换句话说,现在每个...原创 2019-03-01 07:57:05 · 234 阅读 · 0 评论 -
2019.02.26【九省联考2018】【BZOJ5253】【洛谷P4384】制胡窜(后缀自动机SAM)(树上倍增)(线段树合并)
BZOJ传送门洛谷传送门解析:神题啊。。。看了shadowice的题解,不过他有的地方写错了,让我困惑了好一阵,所以这里再写一篇题解。不过基本思路和叙述都和shadowice差不多,修改了一些他写错了的地方。题目要你求一个东西:给出一个字符串和它的某一个子串,问在原串上切两刀(不重复),使得切出来的三个串中至少有一个包含一个该子串,有多少种方案?正难则反,考虑它的对偶问题,切出来的三个...原创 2019-02-26 23:07:40 · 241 阅读 · 0 评论 -
【十二省联考2019】【LOJ3049】【洛谷P5248】【BZOJ5496】字符串问题(SAM优化建图)(拓扑排序)
LOJ传送门洛谷传送门BZOJ传送门解析:瞎写一通成功拿下BZOJ倒数第一(在线丢人 )常数实在是太大了没办法。。。首先我们很显然发现要求的是DAG最长链,这是一个图论问题。只要把图建出来一切都好说。如果建出图有环肯定就咕咕咕了。显然不能暴力建图,考虑怎么优化前缀那部分的连边。建立反串后缀自动机,那么前缀关系就转化成了后缀。树上倍增找到每个串的对应节点,用一个vector存下...原创 2019-04-10 17:00:13 · 311 阅读 · 0 评论 -
【BZOJ1396/2865】识别子串(SAM)(线段树)
传送门题解:建出SAM,能够用来更新答案的是right集合大小为1的,也就是叶子节点,也就是原串的每个位置的代表节点。考虑节点iii,显然[len[fa[i]]+1,len[i]][len[fa[i]]+1,len[i]][len[fa[i]]+1,len[i]]这段区间可以直接被len[fa[i]]+1len[fa[i]]+1len[fa[i]]+1更新。然后对于[1,len[i]−l...原创 2019-09-23 20:43:35 · 148 阅读 · 0 评论 -
【BZOJ3756】Pty的字符串(广义SAM)
传送门题解:广义SAM水题,不是很清楚那些在线构建的为什么能过,应该是出题人没有卡,卡成O(nn)O(n\sqrt n)O(nn)还是绰绰有余的,这样DarkBZOJ上的AC代码基本全灭。8e58e58e5你给我说根号能过?还有,字符串大小直接开8e6,题面没有说大小,我就因为这个RE了若干次。代码:#include<bits/stdc++.h>#define ll...原创 2019-09-23 22:11:23 · 207 阅读 · 0 评论 -
2018.12.15【UOJ35】后缀排序(各种做法(包括SAM))
传送门解析:SAM以外的其他做法:https://blog.csdn.net/zxyoi_dreamer/article/details/84667881SAM做法:在反串上建出SAM,标记每一个反串的前缀终止位置(即原串的后缀起始位置),保留fail树。留下来的fail树就是原串的后缀树。在后缀树上按照字典序进行DFS将遇到的标记一一收回,就完成了后缀数组的构建。没听懂?回去学习...原创 2018-12-15 14:22:58 · 348 阅读 · 0 评论