随笔分类 -  数据结构—后缀自动机

1
摘要:第一、二问: 就是最小的最长公共长度+1,设f[i][j]为a匹配到i,b匹配到j,第一问的转移是f[i][j]=(a[i]==b[j]?f[i 1][j 1]+1:0),第二问的转移是f[i][j]=(a[i]==b[j]?f[i 1][j 1]+1:f[i][j 1]),注意这里更新最小公共长度 阅读全文
posted @ 2019-04-22 14:30 lokiii 阅读(173) 评论(0) 推荐(0)
摘要:SA的话t==0直接预处理出每个后缀的不同串贡献二分即可,然后t==1就按字典序枚举后缀,然后跳右端点计算和当前后缀的前缀相同的子串个数,直到第k个 不过bzoj上会T cpp include include include using namespace std; const int N=1000 阅读全文
posted @ 2019-04-16 18:30 lokiii 阅读(189) 评论(0) 推荐(0)
摘要:对第一个串建SAM,把剩下的串在上面跑,每次跑一个串的时候在SAM的端点上记录匹配到这的最大长度,然后对这些串跑的结果取min,然后从这些节点的min中取max就是答案 注意在一个点更新后它的祖先也会被更新,需要最后按拓扑序向上更新一边 其实二分+hash就行 cpp include include 阅读全文
posted @ 2019-04-15 20:08 lokiii 阅读(110) 评论(0) 推荐(0)
摘要:有一个想法就是暴力建图,把每个A向有和他相连的B前缀的A,然后拓扑一下,这样的图是n^2的; 考虑优化建图,因为大部分数据结构都是处理后缀的,所以把串反过来,题目中要求的前缀B就变成了后缀B 建立SAM,发现在parent树中每个B能走到的A都在子树中,所以保留这个树结构,连边权为0的边; 然后在p 阅读全文
posted @ 2019-04-15 18:53 lokiii 阅读(187) 评论(0) 推荐(0)
摘要:一直WA……找了半天错的发现居然是解密那里的mask其实是不能动的……传进去的会变,但是真实的那个不会变…… 然后就是后缀自动机,用LCT维护parent树了……注意不能makeroot,因为自动机的根是不会变的(同理也不能翻转区间),其实就是低配LCT(?) cpp include include 阅读全文
posted @ 2018-12-07 10:39 lokiii 阅读(161) 评论(0) 推荐(0)
摘要:建个SAM,符合要求的串显然是|right|==1的节点多代表的串,设si[i]为right集合大小,p[i]为right最大的r点,这些都可以建出SAM后再parent树上求得 然后对弈si[i]==1的点,考虑它所代表的串是s(p[i] dis[i]+1,p[i])~s(p[i] dis[fa[ 阅读全文
posted @ 2018-11-24 09:24 lokiii 阅读(195) 评论(0) 推荐(0)
摘要:首先只有lcp(i,j)需要考虑 因为SAM的parent树是后缀的前缀的最长公共后缀(……),所以把这个串倒过来建SAM,这样就变成了求两个前缀的最长公共后缀,长度就是这两个前缀在parent树上的lcs对应的最大长度dis 这里用treedp解决即可,就是合并一下size cpp include 阅读全文
posted @ 2018-11-23 22:01 lokiii 阅读(142) 评论(0) 推荐(0)
摘要:AC自动机比较简单,把询问串做成AC自动机然后模板串边跑变更新即可 SAM是把模板串做成广义SAM,然后每个节点存有几个模板串经过,具体方法是每次更新暴力向上跳直到有时间戳~~我不会证为什么时间复杂度是对的~~,沿途更新个数,查询的时候直接匹配到最后的点然后输出个数即可 cpp include in 阅读全文
posted @ 2018-11-23 19:51 lokiii 阅读(157) 评论(0) 推荐(0)
摘要:把模板串建一个广义SAM 然后在线查询,每次在SAM上预处理出一个a[i]表示i位置向前最多能匹配多长的模板串 二分答案L,dp判断,设f[i]为·~i有几个匹配,转移显然是f[i]=max{f[i 1],f[j]+i j(i a[i]=L\ 0.9 阅读全文
posted @ 2018-11-23 18:39 lokiii 阅读(148) 评论(0) 推荐(0)
摘要:差分之后用SAM求LCS,然后答案就是LCS+1 cpp include include include using namespace std; const int N=2005; int n,m,s[N],b[N],fa[N],ch[N][205],dis[N],cur=1,con=1,la,f 阅读全文
posted @ 2018-11-23 17:01 lokiii 阅读(169) 评论(0) 推荐(0)
摘要:有一个显然的性质就是每个串一定在某个叶子为根的树中是一条直的链 然后因为SAM里是不会有相同状态的,所以以每个叶子为根dfs一遍,并且动态构造SAM(这里的节点u的last指向父亲),最后统计答案就是dis[i] dis[fa[i]]的和 我看别的题解都说和trie有关……然而并没用用到(也可能是用 阅读全文
posted @ 2018-11-23 16:34 lokiii 阅读(144) 评论(0) 推荐(0)
摘要:SAM里的转台不会有重复串,所以答案就是每个right集合所代表的串个数的和 cpp include include include using namespace std; const int N=100005; int T,n,fa[N],ch[N][27],dis[N],cur=1,con=1 阅读全文
posted @ 2018-11-23 15:59 lokiii 阅读(167) 评论(0) 推荐(0)
摘要:多串LCS~~很适合SA但是我要学SAM~~ 对第一个串求SAM,然后把剩下的串在SAM上跑,也就是维护p和len,到一个点,如果有ch[p][c],就p=ch[p][c],len++,否则向fa找最下的有c[p][c]的p,然后len=dis[p]+1,p=ch[p][c],否则就p=root,l 阅读全文
posted @ 2018-11-23 09:39 lokiii 阅读(159) 评论(0) 推荐(0)
摘要:先求出SAM,然后考虑定义,点u是一个right集合,代表了长为dis[son]+1~dis[u]的串,然后根据有向边转移是添加一个字符,所以可以根据这个预处理出si[u],表示串u后加字符能有几个本质不同子串 然后回答的时候在树上跑一下即可 阅读全文
posted @ 2018-11-23 07:57 lokiii 阅读(166) 评论(0) 推荐(0)
摘要:先求个SAM,然后再每个后缀的对应点上标记si[nw]=1,造好SAM之后用吧parent树建出来把si传上去,然后用si[u]更新f[max(u)],最后用j i的[j]更新f[i] 因为每个点u对应长为min(u)~max(u)的串,我们就把它记在max(u)上,最后再统一向前更新,然后更新后的 阅读全文
posted @ 2018-11-22 16:31 lokiii 阅读(140) 评论(0) 推荐(0)
摘要:看上去比较SA,但是在学SAM所以就用SAM来做…… 把串复制一遍接在后面,对这个新串求SAM(这里的儿子节点要用map转移),然后从根节点每次都向最小的转移走,这样走n次转移的串就是答案 阅读全文
posted @ 2018-11-22 14:44 lokiii 阅读(116) 评论(0) 推荐(0)
摘要:海岛冰轮初转腾 见玉兔 玉兔又早东升 阅读全文
posted @ 2018-09-24 16:34 lokiii 阅读(207) 评论(0) 推荐(0)
摘要:就是后缀自动机的板子嘛..构造完自动机之后拓扑一下,记录size,对于size大于k的点和ans取max cpp include include include include using namespace std; const int N=100005; int n,m,a[N],cur=1,c 阅读全文
posted @ 2018-04-25 17:26 lokiii 阅读(131) 评论(0) 推荐(0)
摘要:用manacher找出本质不同的回文子串放在SAM上跑 阅读全文
posted @ 2018-04-20 16:21 lokiii 阅读(126) 评论(0) 推荐(0)
该文被密码保护。
posted @ 2018-03-22 22:01 lokiii 阅读(4) 评论(0) 推荐(0)

1