題意 : 回答第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反向之後得到的...