
SAM
Icefox_zhx
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
bzoj3998 [TJOI2015]弦论(SA/SAM)
求第k小子串。如果t=0,直接拿sa线性搞即可。如果t=1,我复杂度就炸了。。。然而本机和luogu都跑了过去(可见数据之水,逃)。正解大概是SAM,待更新。3.24upd:蒟蒻我终于看懂了SAM的板子orz 顾名思义,SAM就是能识别所有后缀的自动机。我们有一个朴素的构建SAM的想法:把每一个后缀都插到Trie里去!但是这样是O(n^2)的,无论时间还是空间都会炸。怎么办呢?我们要压缩状态,一些原创 2018-03-22 12:49:07 · 406 阅读 · 0 评论 -
bzoj2865 字符串识别(SA+线段树)
与bzoj1396基本一样,不过这题卡内存,SAM跑不过去,只能写SA。 不过蒟蒻懒得写了qaq就不放代码了…原创 2018-06-18 23:10:56 · 310 阅读 · 0 评论 -
bzoj1396 识别子串(SAM+线段树)
我们建SAM,搞出parent树。 然后考虑哪些串是可能的识别子串,显然是那些|Right|=1的节点所代表的串。考虑这样的节点x,它的mn=mx[par[x]]+1,mx=mx[x],结尾字符为原串第r个。则他会对r-mn+1~r贡献一个mn的可能答案,对r-mx+1~r-mn贡献一个 -x+r+1的可能答案。于是两棵线段树分别维护一下最小值即可。#include <bits/st...原创 2018-06-18 11:23:17 · 522 阅读 · 1 评论 -
bzoj3676 [Apio2014]回文串(manacher+SAM)
首先对原串建SAM,并处理出每个点所代表的串出现的次数sz。 用manacher搞出本质不同的回文子串,去SAM上查询出现次数即可。 在SAM上定位这个串的时候倍增查找即可。 复杂度O(nlogn)O(nlogn)O(nlogn) 注意我这样manacher没有处理单点的情况…#include <bits/stdc++.h>using namespace std;#de...原创 2018-06-22 15:39:56 · 329 阅读 · 0 评论 -
bzoj5084 hashit(广义SAM+set动态维护树链的并)
给出的字符串可以很方便的建成Trie树的若干个字符串的形式。 然后我们对Trie树建出广义SAM 那么每次询问的答案就是目前Trie树上所有点在parent树上的点到根的若干树链的并的点i的mx[i]-mx[par[i]] 我们可以用set+dfs序来动态维护树链的并的长度。 注意到x到根的这条树链的贡献其实就是mx[x] 复杂度O(26n+nlogn)O(26n+nlogn)O(26n...原创 2018-06-21 22:56:08 · 423 阅读 · 0 评论 -
bzoj5253 [2018多省省队联测]制胡窜(SAM+线段树合并+树上倍增+数学)
这题细节好多阿orz好毒瘤阿orz首先我们对于每一个询问子串,如果处理出了他的所有出现位置,那么我们反过来求,就是要求用两个断点把所有线段都断开的方案数。处理出所有询问子串的出现位置可以SAM+parent树上倍增来快速定位子串所在节点,这个节点的Right集合就是所有的出现位置。我们可以用线段树合并来维护这个Right集合。复杂度O((Q+n)logn)O((Q+n)logn)O((Q+...原创 2018-05-10 19:05:38 · 845 阅读 · 0 评论 -
bzoj2780 [Spoj]8093 Sevenk Love Oimaster(SAM+dfs序+BIT)
这个问题和bzoj3881基本一模一样。 3881是拿ACAM+树链的并写的,先把询问串建出ACAM,然后拿文本串去更新答案。这道题呢是拿SAM+dfs序+离线+BIT做的。先把文本串建出SAM,在每个点上挂一个vector记录这个节点所属的文本串。然后对于每一个询问串,先跑出它在SAM上的代表节点p,那么他的答案就是p的子树中不同颜色的个数,用dfs序转化为序列就是求区间内不同数的个数。可以离线原创 2018-04-23 21:51:00 · 301 阅读 · 0 评论 -
bzoj4032 [HEOI2015]最短不公共子串(SAM+序列自动机+bfs)
序列自动机就是可以识别所有子序列的自动机,点数O(n)O(n),边数O(26n)O(26n) 每个点的par就是这个点代表的字母上一次出现的位置,因此要记录last[i],表示字母i上一次出现在哪,然后每一个点的儿子i指向他后面出现的第一个字母i的位置。求A最短的子串/子序列不是B的子串/子序列,我们两个自动机一起跑,状态[x][y]表示一个字符串匹配到了A自动机的x节点,B自动机的y节点,因为是原创 2018-04-23 11:02:49 · 403 阅读 · 0 评论 -
bzoj4566 [Haoi2016]找相同字符(SAM)
我们拿A串建出SAM,基数排序处理出拓扑序,算好|Right|。 用B串在SAM上跑,匹配到一个点p时计算当前匹配答案就是(len-mn[p]+1)*ri[p]。当然答案中还应该加上(mx[p]-mn[p]+1)*ri[p],对于所有的p在par树上的祖先,但是我们不能每次都直接跳父亲,这样复杂度会爆炸,因此我们只对p节点统计出现次数+1,然后处理p节点对答案的贡献。我们最后再拓扑序一遍,把剩余节原创 2018-04-23 08:48:36 · 498 阅读 · 0 评论 -
spoj8222 NSUBSTR - Substrings(SAM+dp)
我们首先建出后缀自动机,每个节点的|Right|就是这个节点代表的串的出现次数。可以基数排序做出拓扑序之后倒着更新sz。考虑dp[i]表示长度为i的串最多的出现次数,显然有dp[i]不升。于是我们每次更新一个节点时,其实只要更新dp[mx[i]]即可,最后再倒着更新一遍dp[i]=max(dp[i],dp[i+1])即可。原创 2018-04-11 16:35:51 · 270 阅读 · 0 评论 -
bzoj4516 [Sdoi2016]生成魔咒(SAM+map)
动态在最后字符,问本质不同的子串个数,可以SAM来做。 mx[x]-mn[x]+1=mx[x]-mx[par[x]]就是答案。原创 2018-04-11 14:42:04 · 205 阅读 · 0 评论 -
bzoj2806 [Ctsc2012]Cheat(SAM+单调队列优化dp)
首先我们建出广义SAM,然后对于每一个询问串S,我们处理出len[i],表示最大的S[i-len[i]+1…i]可以被匹配。我们二分答案,dp判定,f[i]表示前i个字符最多匹配多少位。 f[i]=max{f[i−1],f[j]+i−j|i−len[i]<=j<=i−L}f[i]=max\{f[i-1],f[j]+i-j| i-len[i]<=j<=i-L\} j的取值范围是随着i的增大而单调右原创 2018-04-15 20:14:24 · 288 阅读 · 0 评论 -
bzoj5137 [Usaco2017 Dec]Standing Out from the Herd(广义SAM)
首先不得不说,是在下输了。对于广义SAM的构建,蒟蒻之前还存在着很多误区。广义SAM的构建与SAM的构建,主要区别就在于,当你插入一个字符时,可能根本就不会产生新的子串,也就根本不用新建一个节点。什么情况下会发生这种情况?设p=last,要插入字符ch,如果已经存在son[p][ch],记为q,则一定不会产生新的子串(原来在SAM上就可以到达q,所以所有以ch结尾的子串均已存在),对于这种情况我们不原创 2018-03-26 21:20:54 · 738 阅读 · 0 评论 -
bzoj4892 [Tjoi2017]dna(SAM/SA/二分答案+Hash)
在后缀自动机上跑一跑就好啦。O(n)O(n)O(n) SA题解:portalO(nlogn)O(nlogn)O(nlogn) upd:还可以二分答案+Hash来求lcp哟。O(nlogn)O(nlogn)O(nlogn)SAM#include <cstdio>#include <cstring>#include <algorithm>#incl...原创 2018-03-26 15:57:50 · 502 阅读 · 0 评论 -
bzoj3926 [Zjoi2015]诸神眷顾的幻想乡(广义SAM)
广义后缀自动机,就是多主串后缀自动机,一般是先把多个串建出Trie,然后把Trie树建成SAM,这里的R集合定义为Trie上的节点。至于如何构建,与普通SAM差不多,只不过每次的last是Trie上的父亲在SAM中的节点即可。但是你如果没建出Trie树,直接去构建SAM,有可能会有在Trie树上重复的节点,你需要把它判掉,否则在SAM上会存在重复的点,统计一些信息时就可能会出锅(对于此题而言,...原创 2018-03-26 15:12:23 · 322 阅读 · 0 评论 -
bzoj2555 SubString(SAM+lct)
支持在末尾加入一个字符串 查询一个字符串的出现次数 强制在线我们建出SAM,找到这个字符串,如果找不到直接返回0.这个节点的|Right|就是答案。因此我们需要动态维护|Right|.考虑我们构造的过程,把np连到parent树上之后,np到根的路径上的所有点都+1了。而用nq代替q时,需要把v[nq]变成v[q],然后还是np到根的路径上的所有点+1.我们可以用有根树lct来维护这个路径加法。原创 2018-03-24 21:47:35 · 305 阅读 · 0 评论 -
bzoj2946 [Poi2000]公共串(SAM)
求多个串的最长公共子串。首先用第一个串建出SAM。然后用每一个串去SAM去上跑,得到匹配到每个节点的最长长度。这个怎么得到呢?设我们现在匹配到了节点p,长度为len,下一个字符为x,则1)son[p][x]存在,则p=son[p][x],++len2)son[p][x]不存在,在par树上一直往上跳,直到存在son[p][x],len=mx[p]+1,p=son[p][x]。如果不存在这样的p,p=原创 2018-03-24 19:22:08 · 292 阅读 · 0 评论 -
bzoj2882 工艺(SAM+map)
求S的最小循环串。我们构造出SS的SAM,从rt出发,每次选择标号最小的,走m次即可。字符集太大,我们只好map,还好求最小了呢(逃原创 2018-03-24 16:08:39 · 324 阅读 · 0 评论 -
bzoj4199 [Noi2015]品酒大会(SAM+线段树)
这回换了个SAM写,SA的做法见:portal一开始以为可以做到线性…结果写了之后发现还是要挂棵线段树… 我们考虑对反串建SAM,搞出后缀树,这样任意两个后缀的lca就是他们的lcp。于是我们可以在每个lca处统计答案。 不过一个点可能会覆盖一段长度区间,所以要区间修改答案。 复杂度O(26n+nlogn)O(26n+nlogn)O(26n+nlogn)#include <bi...原创 2018-06-26 14:16:27 · 442 阅读 · 0 评论