P2414 NOI2011 阿狸的打字機

2021-09-29 01:14:53 字數 1511 閱讀 7853

打字機上只有28個按鍵,分別印有26個小寫英文本母和』b』、'p』兩個字母。經阿狸研究發現,這個打字機是這樣工作的:

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

·按一下印有』b』的按鍵,打字機凹槽中最後乙個字母會消失。

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

例如,阿狸輸入apapbbp,紙上被列印的字元如下:

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

仔細想想,y中有多少個x,不就是求y的某個節點往上跳fail能不能到達x,因為每個節點的fail一定最多只有一條,所有我們完全可以反向建邊,建出fail樹,那麼我們的問題不就是求x往下能到達多少個y的節點,那這就不是相當於求子樹和了嗎?

再想想,如果把所有y的節點全部賦乙個權值1,那麼不就是求x的最後乙個節點的子樹和嗎?

這樣交上去,又t,真是毒瘤…

那麼我們還能怎麼優化呢?我們每次求子樹和的時候都是暴力求和,時間複雜度確實過不了,但沒關係,求子樹和,我們完全可以用線段樹或者樹狀陣列優化!想想將樹上的點按照dfs序打上標號後,乙個樹的子樹和就相當於被降維打擊了,完全可以看成乙個陣列,這樣就可以簡單的套模板求和啦!我們只需要每次在b操作時,將該點的權值-1,移動root到它的父節點。每次訪問到乙個結束的節點時,一定是有且僅有這個串的節點被標記,這樣就能回答關於這個串的相關詢問啦!

具體細節見**!

由於本蒟蒻線段樹容易寫崩掉,所以選擇了好寫的樹狀陣列。

#include

using

namespace std;

const

int maxn =

1e5+50;

struct trie}}

void

build()

}}}void

dfs(

int u)

}int

lowbit

(int x)

//簡單好寫的樹狀陣列

void

add(

int x,

int val)

intquery

(int x)

void

solve()

}else

if(s[i]

=='b'

)else}}

void

work()

insert()

;build()

;dfs(0

);solve()

;for

(int i=

1;i<=m;i++

)printf

("%d\n"

,ans[i]);

}}automaton;

intmain()

P2414 NOI2011 阿狸的打字機

傳送門 先想想暴力怎麼搞 搞乙個ac自動機 對每個詢問 x,y 把 y 暴力向下匹配 每個點都暴力跳fail 看看x出現了幾次 稍微優化一波 因為有多組詢問 考慮離線 可以把同一組的 y 一起來計算 還是把 y 暴力匹配 看看所有的x 出現了幾次 再來一波優化 考慮什麼時候 x 的出現次數會增加 顯...

P2414 NOI2011 阿狸的打字機

p2414 noi2011 阿狸的打字機 顯然跟處理字串有關,但具體用什麼呢?一次列印有可能會列印之前重複過的,當然是 trie 之後查詢作為子串出現過幾次,看看前面的 trie 當然用 trie 圖了 先考慮暴力,y 所在串的每個字元跳 fail 是否能到 x 的末尾 在 parents 樹尤拉序...

NOI2011 JZOJ2784 阿狸的打字機

有乙個快取槽,設計乙個程式維護下面三個操作 i nser tc 在快取槽末尾插入小寫字元c pri nt 將快取所有字元連線輸出為字串 d elet e 刪除快取槽最後乙個字元 操作總共有 n 個。在所有操作結束之後,要支援 m個詢問。每個詢問都是查詢第 x 次輸出的字串在第 y次輸出的字串中出現了...