[XSY3320] string (AC自动机,哈希,点分治)

XSY3320

前置芝士:回文前缀&& b o r d e r border border
推荐博客
推荐博客

考虑点分治,问题变成求经过重心的回文路径个数。
一条经过重心的回文路径长这样:
在这里插入图片描述

x x x z z z的串与 y y y r o o t root root的串相同。

建出根到每个节点对应的串的AC自动机,并在 f a i l fail fail树上找出每个串的回文前缀。判断根到某个节点对应的串是不是回文串可以用哈希解决。

根据 b o r d e r border border理论,一个回文串的所有回文前缀的长度可以组成一个不超过 O ( l o g n ) O(logn) O(logn)项的等差数列。即若 T k T_k Tk是回文串, T k T_k Tk的最长回文真前缀是 T k − 1 T_{k-1} Tk1 T k − 1 T_{k-1} Tk1的最长回文真前缀是 T k − 2 T_{k-2} Tk2,…, T 2 T_2 T2的最长回文真前缀是 T 1 T_1 T1,那么有 ∣ T i ∣ = ∣ T i − 1 ∣ + d |T_i|=|T_{i-1}|+d Ti=Ti1+d d d d为公差)。

考虑一个点作为 x x x的贡献。设根到 x x x对应的串为 U U U U U U在AC自动机上对应点 X X X。把 U U U的最长回文真前缀看成 T k T_k Tk,那么 T i T_i Ti作为回文串 T T T时,我们要查询有多少个点 y y y,满足根到 y y y对应的串是 U U U的后缀,且长度为 ∣ U ∣ − ∣ T i ∣ = ∣ U ∣ − ∣ T 1 ∣ − ( i − 1 ) d |U|-|T_i|=|U|-|T_1|-(i-1)d UTi=UT1(i1)d,记有 n u m [ i ] num[i] num[i]个符合条件的 y y y。那么最后这个 x x x的贡献就是 ∑ i = 1 k n u m [ i ] \sum_{i=1}^{k}num[i] i=1knum[i],换句话说,我们要求有多少个点 y y y,满足根到 y y y对应的串是 U U U的后缀,且长度 l e n len len符合: l e n ≡ ∣ U ∣ − ∣ T 1 ∣ ( m o d    d ) , ∣ U − T 1 ∣ ≤ l e n ≤ ∣ U ∣ − ∣ T k ∣ len\equiv|U|-|T_1|(\mod d),|U-T_1|\leq len\leq |U|-|T_k| lenUT1(modd),UT1lenUTk

U U U的后缀,即 X X X f a i l fail fail树上的祖先对应的串。我们对 f a i l fail fail d f s dfs dfs,同时开一个数组 c i , j c_{i,j} ci,j 记录当前节点有多少个祖先(包括自己),满足该祖先代表的串的长度 m o d    i = j \mod i=j modi=j

那么最终贡献就是 d f s dfs dfs到的点代表的串长为 ∣ U ∣ − ∣ T k ∣ |U|-|T_k| UTk c d , ( ∣ U ∣ − ∣ T 1 ∣ ) m o d    d c_{d,(|U|-|T_1|)\mod d} cd,(UT1)modd的值 减去 d f s dfs dfs到的点代表的串长为 ∣ U ∣ − ∣ T 1 ∣ − d |U|-|T_1|-d UT1d c d , ( ∣ U ∣ − ∣ T 1 ∣ ) m o d    d c_{d,(|U|-|T_1|)\mod d} cd,(UT1)modd的值。

但这样空间复杂度是 O ( n 2 ) O(n^2) O(n2)的,所以我们考虑分块,只开到 c [ n ] [ n ] c[\sqrt{n}][\sqrt{n}] c[n ][n ]的大小,对于公差大于 n \sqrt{n} n 的,我们暴力跳 f a i l fail fail寻找答案。

猜你喜欢

转载自blog.csdn.net/Emma2oo6/article/details/120565122