【题解】QOJ5256 字符串 数据结构

不要对字符串有本能恐惧,不要认为一个题可以SAM就只能SAM。

首先题意要求求出匹配次数最多的位置的最靠前,最靠后,及个数,看上去没啥特殊的地方,直接考虑求出插在每个位置的匹配次数。

插入 T 后 $P$ 可能的匹配位置有如下 $5$ 种,我们逐一来讨论。

(其实当 $P$ 在整个 $T$ 中出现时,这些出现次数在任意位置插入都有,所以直接数出来然后加上就可以了)


首先①,⑤两种出现一定是 $P$ 原本在 $S$ 中的匹配位置,且不受 $T$ 插入的影响,直接考虑把 $P$ 放到 $S$ 上去做一个匹配,然后求出 PinS 的位置,求前后缀和就可以查询每个位置匹配的①,⑤类串的个数了。


接下来考虑②,④类串,由于是对称的我们直接考虑②,形如 $S[l,i]+T[1,r] = P$。将 $P$ 的后缀与 $T$ 的前缀进行匹配,可以得到一些能够成功匹配的位置,这些位置对应会有一些 $P$ 的前缀多余需要被 $S[1,i]$ 的一个后缀匹配。

所以对 $P$ 求出这些可能和 $T$ 前缀匹配的位置,将剩余的前缀拿出来,统计这些前缀作为 $S[1,i]$ 的某个后缀的次数,使用 fail 树即可,将 $P$ 的 fail 树建出来后,可能匹配到的前缀是 fail 树上到根的路径,所以匹配的次数就是到根路径上满足条件的前缀的个数。


考虑③类串,$P=S[l,i]+T+S[i+1,r]$ 中求 $l,r$ 的个数,首先得求出 $T$ 在 $P$ 中匹配的位置,这些位置前面的前缀和对应的后面的后缀可以匹配到 $S[l,i],S[i+1,r]$ 中的部分, 我们建出 $P$ 和 $P$ 反串的 fail 树,同时维护 $S[l,i],S[i+1,r]$ 和 $P$ 的前后缀的匹配量,接下来我们就要查询 $P$ fail 树和 $P$ 反串 fail 树上到根的路径上对应的前缀和后缀对使得中间可以匹配 $T$。

即在 fail 树上做双祖先数点*问题,直接离线后在第一棵树上维护到根路径上的信息,在第二课子树进行一个区间加单点查(扫描第一个树祖先的信息,ds维护第二棵树上每个点的祖先个数)。

*双路径数点:在有若干点对 $(a_i,b_i)$,要求 $a_i\in 1\to u,b_i\in1\to v$ 的 $i$ 的个数。

时间复杂度 $O((|P|+|S|)\log |P|+|T|)$。

较为可读但是巨屎无比的代码。

一个细节是③类串的边界处有可能会被和②类和④类重复计算,解决办法很多比如需要钦定③类串中左右部分必须非空。

posted @ 2023-11-28 21:21  寂静的海底  阅读(15)  评论(0编辑  收藏  举报  来源