日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)

發布時間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接: https://www.lydsy.com/JudgeOnline/problem.php?id=2434

題解:

我寫的是離線做法,不知道有沒有在線做法。

轉化一波題意,\(x\)在AC自動機上代表的字符串在\(y\)代表的字符串中出現的次數等于\(x\)在fail樹的子樹內有多少個點是\(y\)點Trie樹上的祖先。

然后不難得到做法: 將詢問離線按照\(y\)在AC自動機上的id排序(一個正常的構建Trie的方式建出來應該就滿足節點的編號是它的Trie樹DFS序).

在Trie樹上DFS, 同時回答詢問, 用樹狀數組維護即可

代碼

#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std;const int N = 1e5; const int S = 26; struct Edge {int v,nxt; } e[(N<<1)+3]; struct Query {int x,y,id;bool operator <(const Query &arg) const{return y<arg.y;} } qr[N+3]; int fe[N+3]; int dfn[N+3]; int fa[N+3]; int son[N+3][S+3]; int fail[N+3]; char str[N+3]; int stk[N+3]; int id[N+3]; int que[N+3]; int bit[N+3]; int ord[N+3]; int ans[N+3]; int sz[N+3]; int n,q,siz,m,cnt,en;void addval(int lrb,int val) {while(lrb<=cnt){bit[lrb] += val;lrb += (lrb&(-lrb));} }int querysum(int rb) {int ret = 0;while(rb){ret += bit[rb];rb -= (rb&(-rb));}return ret; }void addedge(int u,int v) {en++; e[en].v = v;e[en].nxt = fe[u]; fe[u] = en; }void buildTrie() {int u = 0,tp = 0; stk[tp] = 0;for(int i=1; i<=n; i++){if(str[i]=='B'){stk[tp] = 0; tp--;u = stk[tp];}else if(str[i]=='P'){m++; id[m] = u;}else{str[i]-=96;if(!son[u][str[i]]) {siz++; son[u][str[i]] = siz;}u = son[u][str[i]];tp++; stk[tp] = u;}} }void buildACA() {int head = 1,tail = 0;for(int i=1; i<=S; i++) {if(son[0][i]) {tail++; que[tail] = son[0][i];} fail[son[0][i]] = 0;}while(head<=tail){int u = que[head]; head++;addedge(fail[u],u); addedge(u,fail[u]);for(int i=1; i<=S; i++){if(son[u][i]) {fail[son[u][i]] = son[fail[u]][i]; tail++; que[tail] = son[u][i];}else {son[u][i] = son[fail[u]][i];}}} }void dfs(int u) {cnt++; dfn[u] = cnt;sz[u] = 1;for(int i=fe[u]; i; i=e[i].nxt){if(e[i].v==fa[u]) continue;fa[e[i].v] = u;dfs(e[i].v);sz[u] += sz[e[i].v];} }int main() {scanf("%s",str+1); n = strlen(str+1);scanf("%d",&q);buildTrie();buildACA();for(int i=1; i<=q; i++){int x,y; scanf("%d%d",&x,&y);qr[i].x = id[x]; qr[i].y = id[y]; qr[i].id = i;}dfs(0);sort(qr+1,qr+q+1);int u = 0,tp = 0,j = 0; stk[tp] = 0; addval(dfn[u],0);for(int i=1; i<=n; i++){if(str[i]=='B'){addval(dfn[u],-1);stk[tp] = 0; tp--;u = stk[tp];}else if(str[i]=='P'){while(j<q && qr[j+1].y==u){j++;ans[qr[j].id] = querysum(dfn[qr[j].x]+sz[qr[j].x]-1)-querysum(dfn[qr[j].x]-1);}}else{u = son[u][str[i]];tp++; stk[tp] = u;addval(dfn[u],1);}}for(int i=1; i<=q; i++){printf("%d\n",ans[i]);}return 0; }

總結

以上是生活随笔為你收集整理的BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。