SAM + 根号分治.
每次询问的 $k$ 都是一样的,可以记一个常数 $p=kq$ ,考虑根号分治,对 $k\le q$ 和 $k>q$ 两种情况讨论.
$k\le q$
每次询问的串长不会超过 $\sqrt p$ ,可以直接枚举 $w$ 的每个子串 $w[l,r]$ .
算出这个子串在 $s$ 中出现的次数,再乘上 $[l,r]$ 这个区间在第 $a$ 到第 $b$ 个区间出现的次数,就是这个子串对询问贡献.
前者可以在串 $s$ 的 SAM 上找出 $w[l,r]$ 对应的状态,其 right 集合大小即为出现次数.
后者可以将 $[l,r]$ 在 $m$ 个区间中出现的所有位置存在 vector 中,二分找出 $a,b$ 的位置,做差即为所求.
时间复杂度 $O(qk^2\log m)=O(p\sqrt p \log m)$ .
$k> q$
询问的次数不超过 $\sqrt p$ ,对于每次询问,我们都将第 $a$ 个区间到第 $b$ 个区间拿出来,考虑每个区间 $[l,r]$ 的贡献.
$w[l,r]$ 在串 $s$ 中出现的次数等价于 $s$ 有多少个前缀与 $w[1,r]$ 的 LCS 长度不小于 $r-l+1$ .
将 $w[1,r]$ 在 SAM 上对应的位置找出,倍增查找出其深度最浅的满足 $maxlen\ge r-l+1$ 的祖先.
其 right 集合大小即为所求.
注意在给 $w[1,r]$ 定位时,若沿着失配边往回跳,有效的后缀长度就会改变.
时间复杂度 $O(q(k+m\log n))=O(p+m\sqrt p\log n)$ .
1 | //%std |