XSY3320
前置芝士:回文前缀&&borderborderborder
推荐博客
推荐博客
考虑点分治,问题变成求经过重心的回文路径个数。
一条经过重心的回文路径长这样:
xxx到zzz的串与yyy到rootrootroot的串相同。
建出根到每个节点对应的串的AC自动机,并在failfailfail树上找出每个串的回文前缀。判断根到某个节点对应的串是不是回文串可以用哈希解决。
根据borderborderborder理论,一个回文串的所有回文前缀的长度可以组成一个不超过O(logn)O(logn)O(logn)项的等差数列。即若TkT_kTk是回文串,TkT_kTk的最长回文真前缀是Tk−1T_{k-1}Tk−1,Tk−1T_{k-1}Tk−1的最长回文真前缀是Tk−2T_{k-2}Tk−2,…,T2T_2T2的最长回文真前缀是T1T_1T1,那么有∣Ti∣=∣Ti−1∣+d|T_i|=|T_{i-1}|+d∣Ti∣=∣Ti−1∣+d(ddd为公差)。
考虑一个点作为xxx的贡献。设根到xxx对应的串为UUU,UUU在AC自动机上对应点XXX。把UUU的最长回文真前缀看成TkT_kTk,那么TiT_iTi作为回文串TTT时,我们要查询有多少个点yyy,满足根到yyy对应的串是UUU的后缀,且长度为∣U∣−∣Ti∣=∣U∣−∣T1∣−(i−1)d|U|-|T_i|=|U|-|T_1|-(i-1)d∣U∣−∣Ti∣=∣U∣−∣T1∣−(i−1)d,记有num[i]num[i]num[i]个符合条件的yyy。那么最后这个xxx的贡献就是∑i=1knum[i]\sum_{i=1}^{k}num[i]∑i=1knum[i],换句话说,我们要求有多少个点yyy,满足根到yyy对应的串是UUU的后缀,且长度lenlenlen符合:len≡∣U∣−∣T1∣(modd),∣U−T1∣≤len≤∣U∣−∣Tk∣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∣。
UUU的后缀,即XXX在failfailfail树上的祖先对应的串。我们对failfailfail树dfsdfsdfs,同时开一个数组ci,jc_{i,j}ci,j 记录当前节点有多少个祖先(包括自己),满足该祖先代表的串的长度 modi=j\mod i=jmodi=j。
那么最终贡献就是dfsdfsdfs到的点代表的串长为∣U∣−∣Tk∣|U|-|T_k|∣U∣−∣Tk∣时cd,(∣U∣−∣T1∣)moddc_{d,(|U|-|T_1|)\mod d}cd,(∣U∣−∣T1∣)modd的值 减去 dfsdfsdfs到的点代表的串长为∣U∣−∣T1∣−d|U|-|T_1|-d∣U∣−∣T1∣−d时cd,(∣U∣−∣T1∣)moddc_{d,(|U|-|T_1|)\mod d}cd,(∣U∣−∣T1∣)modd的值。
但这样空间复杂度是O(n2)O(n^2)O(n2)的,所以我们考虑分块,只开到c[n][n]c[\sqrt{n}][\sqrt{n}]c[n][n]的大小,对于公差大于n\sqrt{n}n的,我们暴力跳failfailfail寻找答案。