P2414 NOI2011 阿狸的打字機

2022-05-20 02:18:47 字數 2434 閱讀 3167

傳送門

先想想暴力怎麼搞

搞乙個ac自動機

對每個詢問 x,y

把 y 暴力向下匹配

每個點都暴力跳fail

看看x出現了幾次

稍微優化一波

因為有多組詢問

考慮離線

可以把同一組的 y 一起來計算

還是把 y 暴力匹配

看看所有的x 出現了幾次

再來一波優化

考慮什麼時候 x 的出現次數會增加

顯然是在 y 的某個節點的 fail 路徑上

因為每個點只有乙個 fail

所以所有的 fail 構成了一顆樹

如果把 fail 看成無向邊,根節點為自動機的根節點

那就相當於問在fail樹的x的結束節點的子樹中,有幾個節點屬於y

那麼詢問 x,y 就只要在ac自動機上跑到y

路過的每乙個節點就把 記錄值+1

然後詢問 在fail樹中 x 的結束節點的子樹 記錄值之和為多少

對於這種對子樹的詢問

用什麼方法最好呢?

樹鏈剖分!

為什麼這麼麻煩

雖然不可能用樹剖

但是可以用樹剖的思想

給每個節點乙個dfs序

在ac自動機上跑的時候

每經過乙個節點就把該節點的dfs序的值+1

退出該節點時就-1

然後詢問就像樹剖的子樹詢問一樣了

因為每次是單點修改,區間求和

所以用樹狀陣列維護一波就好了

總結一下

把每個操作離線

把y相同的詢問放在一起

dfs一波,每次找到結束標記

就把相關的詢問處理

具體的實現在**裡

#include#include

#include

#include

#include

#include

using

namespace

std;

inline

intread()

returnx;}

const

int n=1e5+7

;char

s[n];

intfa[n];

intn,m;

int c[n][27],pd[n],fail[n],cnt,las[n];//

las[i]表示第i個串的結束節點的位置

inline void build()//

處理操作並構造出ac自動機

}}//

以下為預處理fail並構造出fail樹

queue q;

int fir[n],from[n],to[n],cnt2;//

存fail樹

inline void add(int a,int

b)//

向fail樹中加邊

int c[n][27];//

存原ac自動機的結構,因為處理fail時會把ac自動機的結構改變

//等等還要用原來的結構來dfs處理詢問

void

pre()

}}//

以上為預處理fail並構造出fail樹

//第一波dfs確定dfs序

int dfn[n],sz[n],cnt3;//

dfn是dfs序,sz是子樹大小

void dfs1(int

x)//

以下為樹狀陣列

intt[n];

inline

void add(int x,int v)

inline

int query(int

x)//

以上為樹狀陣列

//以下存詢問

struct

data

d[n];

inline

bool cmp(const data &a,const data &b)

int l[n],r[n];//

l[i]表示排序後y值為i的區間的左端點,r為右端點

//以上存詢問

void dfs2(int

x) add(dfn[x],-1);//

退出時值要改回來

}int

ans[n];

intmain()

r[d[m].y]=m;

dfs1(

0);//

確定dfs序

dfs2(0);//

dfs處理詢問

for(int i=1;i<=m;i++)

ans[d[i].id]=d[i].ans;//

按原來的順序把答案放到答案陣列裡

for(int i=1;i<=m;i++) printf("

%d\n

",ans[i]);

return0;

}

P2414 NOI2011 阿狸的打字機

打字機上只有28個按鍵,分別印有26個小寫英文本母和 b p 兩個字母。經阿狸研究發現,這個打字機是這樣工作的 輸入小寫字母,打字機的乙個凹槽中會加入這個字母 這個字母加在凹槽的最後 按一下印有 b 的按鍵,打字機凹槽中最後乙個字母會消失。按一下印有 p 的按鍵,打字機會在紙上列印出凹槽中現有的所有...

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次輸出的字串中出現了...