BZOJ 2434 阿狸的打字機

2021-09-11 19:16:31 字數 1791 閱讀 6535

題意 : 回答第x個模式串在第y個模式串**現了幾次。資料範圍∑n,

∑m,q

≤105

\sum_n,\sum_m,q\leq10^5

∑n​,∑m

​,q≤

105顯然可以離線,對於相同y的詢問集中處理,暴跳fail的時候開個桶丟進去,最後把有用的提出來。

但是還是太慢了。

考慮問題本質:對於一組詢問x,y

x,yx,

y實際上是在問屬於串y

yy的節點有多少fai

lfail

fail

邊指向xxx

可以注意到每個點有且僅有乙個fai

lfail

fail

於是從這個點的fai

lfail

fail

向這個點連邊

然後就是dfs序bit維護

但是插入串串太慢了

我們考慮在原來的trie樹上走,進入乙個點時+1,離開時-1,避免了重複插入刪除。

這樣對於不同的x

xx也能繼續進行回答。

因為沒特判沒有關於落在這個點上的串的詢問導致re了一上午

#include

#include

#include

#include

const

int n =

1e5+7;

int pcnt =

1, endp[n]

, ecnt, last[n]

;struct trie t[n]

;struct graph e[n*5]

;inline

void

add(

int u,

int v)

int xcnt;

inline

void

ins(

char

*ss)}}

inline

void

getfail()

}int dfn[n]

, c[n*10]

, low[n]

;int cnt;

inline

intlbt

(int x)

inline

void

modify

(int x,

int k)

inline

intgetc

(int x)

inline

void

dfs1

(int x)

struct ques q[n]

;bool

operator

<

(ques a, ques b)

int lastans[n]

, sum[n]

;char ss[n]

;int n, ql[n]

, qr[n]

;inline

void

dfs2

(int x)

intmain()

dfs2(1

);for(

int i =

1; i <= n; i++

) lastans[q[i]

.id]

= q[i]

.ans;

for(

int i =

1; i <= n; i++

)printf

("%d\n"

, lastans[i]);

return0;

}

bzoj 2434 阿狸的打字機 fail樹的性質

如果a串是另b串的字尾,那麼在trie圖上沿著b的fail指標走一定可以走到a串。而a串在b串裡出現多少次就是它是多少個字首的字尾。所以把fail邊反向建樹維護個dfs序就行了。並不是很難。但沒想出來tat 1 include2 include3 include4 include5 define n...

2434 Noi2011 阿狸的打字機

題目鏈結 題目大意 初始字串為空,首先給定一系列操作序列,有三種操作 1.在結尾加乙個字元 2.在結尾刪除乙個字元 3.列印當前字串 然後多次詢問第x個列印的字串在第y個列印的字串中出現了幾次 題解 建出trie 新增乙個字元 新建乙個子節點 若存在在不用新建 進入該子節點 刪除乙個字元 返回到父親...

BZOJ2434 NOI2011 阿狸的打字機

發現一種新的思路,以前從來沒有見過的,即ac自動機的fail樹。這一題我們先考慮暴力,從root往y的最後乙個點走,如果走到了x的末點,ans 如果通過fail指標走到了x的末點,ans 反過來考慮,從x的末點開始,如果當前點在y串或者通過反向的fail到了y串,ans 又發把fail反向之後得到的...