「总结」后缀自动机

最近刷了一下后缀自动机。

题其实做了也不少了,稍微有一点理解。(教练:得理解深刻)

1.我个人认为$parent$树其实是一颗虚树(最近又学了虚树,做了三道题),虚树的思想是只留存关键点以及关键点的$lca$。

$parent$树其实相当于后缀树的虚树,只留存了一些关键点。可以发现对于同一个$right$集合来说,在后缀树上有很多节点的$right$集合是完全相同的,这样在后缀树上这些节点其实是一段从上到下的连续的,度为1的节点。$SAM$把它们压在一起,用$MIN,MAX$的长度来代表这个节点所包含的集合(对于给定的$right$集合,只要再给出长度就可以确定子串),这样实现了对后缀树空间的优化。

2.$trans$转移边是相当于在结尾加入字符,$parent$树边其实是相当于在开头加入字符。

3.每个前缀节点都会丢失一个后缀信息(就是最长前缀,因为无法再从前面加字符了)。

4.$len$值代表的是一条从原点经过$trans$边到达某个节点的最长路径。

5.$parent$树上前缀节点与其父亲的$len$相减就是本质不同子串个数。

 

题列(全是板子题):

1.弦论

如果是本质不同的话,只需要强制每个节点的$right$集合大小为$1$即可,先$dp$一次求出路径数(从某个点开始的路径数等于从这个点代表的前缀所包含的子串个数),这样直接在$trans$上从小到大枚举转移即可。

如果是本质可以相同的话,求出每个节点的$right$集合大小即可,仍然$dp$一次求出路径,不过求出的是$right$集合的总和,同样在$trans$上从小到大枚举转移即可。

可以发现本质不同和本质相同的区别就是在于$right$集合是否可以算作多次,而从源点到某个点的路径数就是以这个点的$right$集合为出现位置的子串个数。

 

2.诸神眷顾的幻想乡

这个题其实挺简单的,是广义后缀自动机,在$trie$树上的应用。题目给出$trie$树且仅有$20$个叶子节点,我们直接暴力插入20个$trie$数进入后缀自动机,每到一个节点就将当前的终止节点记录下来,从$trie$上回溯的时候将终止节点返回这个点。

这样建出来之后直接求本质不同子串即可。

广义后缀自动机就是通过终止节点的变化来实现分离多个串的,理论上也说的通,终止节点代表的是一个串的可匹配结尾的子串。

 

3.公共串

板子题了。

对一个串建后缀自动机,然后让其他串在自动机上跑,跑到某个节点就记录一下匹配长度,同时将$parent$树上的子节点的匹配信息转移到父亲节点上。

最终将其他串全部都经过的节点的最长长度取$min$,再和这个节点的$len$取$min$即可。

公共串匹配仍然是利用了$right$集合的包含性所代表的子串匹配含义。

 

4.差异

前两项可以直接求,求得其实是各个后缀的最长公共前缀的长度,首先反转串,变为各个前缀的各个最长公共后缀的长度。

在$parent$树上所有前缀节点互相的$lca$的$len$值的和。直接树形$dp$即可。

$parent$树上$lca$及其父链的含义其实是两个前缀的公共后缀集合。

 

5.工艺

叫什么最小循环位移。

文本串复制两次加入后缀自动机,从源点开始每次跑字典序最小的$trans$边,跑到长度为$n$就停止即可。

复制两次就保证了可以以任何一个位置为起点。

 

6.生成魔咒

板子题,求本质不同子串。

建后缀自动机之后直接用$parent$所有前缀节点父子的$len$值相减就可以得到当前$right$集合含结尾的子串个数,累加起来其实就是本质不同子串(right集合不同的子串)。

 

7.SubString

本来也没什么难得。

但是由于强制在线所以就变得麻烦了一点。

用$LCT$动态维护$parent$树,然后一个一个操作进行$link,cut$同时动态维护子树$right$集合大小即可。

其实就是数据结构结合后缀自动机的一个经典应用了。

 

8.Cheat

仍然是板子。

首先可以看出$L_0$的单调性,那么我们二分答案。

然后首先让模式串在文本串上面匹配得到每个位置能够匹配的最长长度。

设位置$i$匹配的最长长度是$mx[i]$

然后考虑用$dp$来$check$二分。

这样我们设$dp[i]$为串的前$i$个位置匹配的最长长度。

那么得到转移:

$$dp[i]=\max\limits_{j=i-mx[i]}^{i-mid}{dp[j]+i-j}$$

但是复杂度是$O(n^2)$的,只能得到75分。

可以发现对于每个串来说$i-mx$值都是单调不降的。

那么我们用单调队列优化他即可。

最终复杂度$O(nlogn)$

后缀自动机和$dp$结合的经典例子。

 

9.品酒大会

和差异那道题几乎一模一样,只不过要求方案和最值两个。

同样的找到每个节点的$lca$并且将之计入$lca$的$len$的方案,这样对$len$取一个后缀和,就的到了全部长度的方案。

最值的话因为有负数所以麻烦一些,要记录最大和最小两个值,同样在树形$dp$的时候求出最值,同样对所有的$len$取一个后缀$max$即可。

还是$parent$树的树形$dp$的经典应用。

 

未完。

posted @ 2019-11-05 08:10  Lrefrain  阅读(213)  评论(3编辑  收藏  举报