像潮落潮涌,送我奔向自由。|

寂静的海底

园龄:3年2个月粉丝:59关注:15

【题解】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 的个数,首先得求出 TP 中匹配的位置,这些位置前面的前缀和对应的后面的后缀可以匹配到 S[l,i],S[i+1,r] 中的部分, 我们建出 PP 反串的 fail 树,同时维护 S[l,i],S[i+1,r]P 的前后缀的匹配量,接下来我们就要查询 P fail 树和 P 反串 fail 树上到根的路径上对应的前缀和后缀对使得中间可以匹配 T

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

*双路径数点:在有若干点对 (ai,bi),要求 ai1u,bi1vi 的个数。

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

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

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

posted @   寂静的海底  阅读(33)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起