1. 程式人生 > >【BZOJ】2434: [Noi2011]阿貍的打字機 AC自動機+樹狀數組+DFS序

【BZOJ】2434: [Noi2011]阿貍的打字機 AC自動機+樹狀數組+DFS序

log 字符串 html 有趣的 http .com dfs 個性 blog

【題意】阿貍喜歡收藏各種稀奇古怪的東西,最近他淘到一臺老式的打字機。打字機上只有28個按鍵,分別印有26個小寫英文字母和‘B‘、‘P‘兩個字母。

經阿貍研究發現,這個打字機是這樣工作的:

l 輸入小寫字母,打字機的一個凹槽中會加入這個字母(這個字母加在凹槽的最後)。

l 按一下印有‘B‘的按鍵,打字機凹槽中最後一個字母會消失。

l 按一下印有‘P‘的按鍵,打字機會在紙上打印出凹槽中現有的所有字母並換行,但凹槽中的字母不會消失。

我們把紙上打印出來的字符串從1開始順序編號,一直到n。打字機有一個非常有趣的功能,在打字機中暗藏一個帶數字的小鍵盤,在小鍵盤上輸入兩個數(x,y)(其中1≤x,y≤n),打字機會顯示第x個打印的字符串在第y個打印的字符串中出現了多少次。

【算法】AC自動機+樹狀數組+DFS序

【題解】首先根據操作序列建AC自動機,"B"就返回跳過來的節點,“P”就標記為一個串的結尾節點。

詢問AC自動機中一個串A在另一個串B中出現幾次?

從根開始走整個串A,標記到達的節點為1,那麽就是詢問B在fail樹上的子樹中有多少節點為1。

詢問可以用樹狀數組維護DFS序來區間查詢,這部分復雜度O(n log n)。那怎麽修改詢問串A?

將詢問離線按串A的編號順序排列(本質上是按DFS序排序),利用一個性質【對每個點入棧+1,出棧-1,那每個點到根的前綴和就是到根的路徑(星系探索)】。

所以按順序枚舉串A,加入新節點+1,“B”退格-1,這些+1-1都在樹狀數組上單點修改,遇到詢問就回答(相當於前綴和)。因為串A都是AC自動機中的串,所以不會有fail的問題。

總復雜度O(n log n)。

【BZOJ】2434: [Noi2011]阿貍的打字機 AC自動機+樹狀數組+DFS序