前置芝士:回文前缀&& 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} Tk−1, T k − 1 T_{k-1} Tk−1的最长回文真前缀是 T k − 2 T_{k-2} Tk−2,…, T 2 T_2 T2的最长回文真前缀是 T 1 T_1 T1,那么有 ∣ T i ∣ = ∣ T i − 1 ∣ + d |T_i|=|T_{i-1}|+d ∣Ti∣=∣Ti−1∣+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 ∣U∣−∣Ti∣=∣U∣−∣T1∣−(i−1)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| len≡∣U∣−∣T1∣(modd),∣U−T1∣≤len≤∣U∣−∣Tk∣。
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| ∣U∣−∣Tk∣时 c d , ( ∣ U ∣ − ∣ T 1 ∣ ) m o d d c_{d,(|U|-|T_1|)\mod d} cd,(∣U∣−∣T1∣)modd的值 减去 d f s dfs dfs到的点代表的串长为 ∣ U ∣ − ∣ T 1 ∣ − d |U|-|T_1|-d ∣U∣−∣T1∣−d时 c d , ( ∣ U ∣ − ∣ T 1 ∣ ) m o d d c_{d,(|U|-|T_1|)\mod d} cd,(∣U∣−∣T1∣)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寻找答案。