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

「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)\) 实际上常数非常大?

posted @ 2021-02-17 16:25  chasedeath  阅读(160)  评论(0编辑  收藏  举报