1. 程式人生 > 其它 >CF587F Duff is Mad

CF587F Duff is Mad

  • 給定 \(n\) 個字串 \(s_{1 \dots n}\)
  • \(q\) 次詢問 \(s_{l \dots r}\)\(s_k\) 中出現了多少次。
  • \(n,q,\sum_{i=1}^n |s_i| \le 10^5\)

  字串 根號分治

  首先,建立 AC 自動機。

  考慮暴力,就是將 \(s_{l\sim r}\) 的在 AC 自動機的終止節點的子樹權值 +1,然後答案就是 \(s_k\) 在 AC 自動機上面對應路徑的權值之和。

  考慮差分之後掃描線,我們只要支援求將 \(s_{1 \sim cur}\) 的終止節點子樹權值 \(+1\) 後,\(s_k\)

在 AC 自動機上面對應路徑的權值之和了。

  然後複雜度是 \(\mathcal O(\max\{|S_i|\} q \log_2 L)\) 的,其中 \(L = \sum |S_i|\)

  本來想使用樹鏈剖分進行進一步優化的,但是因為 AC 自動機的路徑在 Fail 樹上不連續,因此我們只能暴跳然後求和。

  但是我們可以根據字串長度考慮根號分治

  具體地,對於 \(|s_k| \ge B\),我們可以將這些串對應的詢問單獨拿出來,然後將 \(s_k\) 在 AC 自動機上面對應的路徑權值 +1,然後在對於每個 \(i\),求出如果 \(i \in [l, r]\)\(s_i\)

對於 \(s_k\) 的答案的貢獻,這個只要在樹上面 DFS 然後字首和即可求解,總複雜度 \(\mathcal O(\frac{L^2}{B})\)

  對於 \(|s_k| < B\),直接使用暴力,總複雜度就是 \(\mathcal O(q B\log_2 L)\)

  根據均值不等式,當 \(B = \frac{L}{\sqrt{q\log_2 L}}\) 的時候複雜度最優,為 \(\mathcal O(L\sqrt{q\log_2 L})\)

  程式碼

  當然,如果第一部分寫醜了直接樹狀陣列多了個 \(\log_2\),那麼也是可以調整塊長然後通過的:程式碼