AC 自动机小记
题目
P9196 [JOI Open 2016] 销售基因链 / Selling RNA Strands
前后缀信息考虑放到字典树上去,则建出两棵字典树后,找到前缀字典树的一个节点的子树内的结尾节点与后缀字典树的一个节点的子树内的结尾节点的交集,显然可以转化为两段连续的 dfn 值,于是离线二维数点即可
P2414 [NOI2011] 阿狸的打字机
首先题目中的操作明显放到字典树上比较好维护,删除时回到父亲节点即可
然后查询操作表面上是单模匹配,但是多次查询且没有字符串总长度的限制,于是考虑在 ACAM 的失配树上做这件事
我们记 \(ed_i\) 表示第 \(i\) 个字符串在字典树上以哪个节点结尾,那么相当于查询失配树上的字数和,树状数组轻松维护
但是匹配串的总长度没有限制,我们发现这样一个性质:匹配串一定在字典树上出现过,也就是我们匹配的时候,走过的点连起来是从根出发的一条链,于是考虑离线,然后去 dfs 整棵树,每次进入一个节点加上他的贡献,离开的时候减去他的贡献,这样贡献就为一条链,可以处理查询
P14363 [CSP-S 2025] 谐音替换
考虑怎样的替换合法,设被替换的区间为 \([l,r]\),则 \(l,r\) 分别都在 \(t1,t2\) 的最长公共前后缀里
此类问题比较像多模匹配,考虑上 ACAM,但是两个字符串实在不好维护,考虑转化成一个,并且能够去匹配
首先,要保证 \(s1,s2\) 里含有 \(t1,t2\) 不是公共前后缀的一部分,我们需要把这一部分区分开,如果直接把 \(s1,s2\) 中非最长公共前缀后缀的字串拼成一段,有可能长度不等但匹配上,此时考虑在前后各加一个特殊字符 #,这样就保证这部分的匹配
然后是 \(s1,s2\) 中可以拥有的 \(t1,t2\) 公共前缀的后缀,公共后缀的前缀部分,我们可以直接把 \(s1,s2\) 的最长前后缀拼在前后面,这样查询就不重不漏
形式话地:将一个变换 \(s1 \rightarrow s2\) 表示为 \(ABC \rightarrow ADC\),其中 \(A,C\) 是最长公共前后缀,那么将其转换为 \(A\#BD\#C\)
特别注意 \(s1 = s2\) 的情况,特殊处理一下即可

浙公网安备 33010602011771号