「ROI 2019 Day2」模式串查找 (口胡)

设$S=\sum |w_i|$

显然我们需要一个树形数据结构来维护题目中添加字符的操作

归纳一下,需要实现的操作就是:

1.添加一个新串

2.在当前串中分裂一段区间$[L,R]$

3.将一个串复制$k$次

将每一个单字符视为一个节点,考虑用一个可持久化的平衡树来维护上述操作,比如可持久化非旋$\text{Treap}$

题解中给出的2-3-Tree不知道效果怎么样

2,3操作增加的数量为$\log$级别,最终的节点总数为$O(S+n\log S)$

接下来需要实现的操作是合并两个子串的信息,显然在合并时计算跨过两个节点的串匹配模板串的次数

容易想到记录后缀匹配的$kmp$指针,但是这样的指针难以完成合并操作

为了计算这个,我们需要维护这个串的前缀/后缀 在 原串上最长的匹配子段

此时一个节点的信息可以用$(l1,r1),(l2,r2),k$来表示,其中$k$标记了这个串是否整个出现在模板串中

合并子串$A,B$信息:

1.求出前缀/后缀匹配,以前缀为例:

1-1.如果$A$无法完全匹配,则匹配前缀为$A$的匹配前缀

1-2.$A$能够完全匹配,设$A$在原串对应$L,R$,$B$的最长匹配前缀在模板串匹配起始位置为$P$

我们需要在$[L,R]$之后借上$P$开始的一段后缀,而$[L,R]$出现在模板串中的位置对应着后缀数组上一段$rank$区间

取模板串反向后缀数组,求出与$R$匹配长度超过$R-L+1$的$rank$区间$[l,r]$

则我们需要找到$[l,r]$中$sa[i]+1$与$P$最长的$LCP$,显然是一个求临近$rank$的问题,可以在线主席树二分解决

由此得到最长前缀为$A$串再加上额外匹配得到的部分

$O(\log m)$完成

2.求出跨过两个串的完美匹配个数

容易得到前串后缀对应的$\text{kmp}$指针,后串前缀对应反向的$\text{kmp}$指针

实际上就是求出这两个指针不断失配时相加恰好完全匹配的个数

注意到,实际上这个询问是完全可以离线

可以通过在线得到的匹配情况,离线得到询问得到询问答案,再从叶子开始重新计算每个节点的答案

比较暴力的做法是:

建立两棵$\text{kmp}$树,在第一棵树上$\text{dfs}$,加入祖先对应的位置,然后再第二棵树上查询祖先匹配的个数

可以用$\text{dfs}$序+差分树状数组维护,复杂度为$O(\log m)$

因此总体复杂度为$O((S+n\log S)\log m)$ 实际上常数非常大?