BZOJ 2434 阿狸的打字机
生活随笔
收集整理的這篇文章主要介紹了
BZOJ 2434 阿狸的打字机
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://www.lydsy.com/JudgeOnline/problem.php?id=2434
思路:建立fail樹,并找出dfs序,那剩下要做的就是每次找到一個串的位置,然后詢問它的區間里面有多少我當前串的節點,具體做法見代碼。
#include<cstdio> #include<cmath> #include<iostream> #include<cstring> #include<algorithm> #include<queue> struct edge{int to,next,id; }que[500005]; int fail[500005],sz,ch[500005][26],root,num,hw,low[500005],dfn[500005]; char s[500005]; int pos[500005],id,fi[500005],first[500005],next[500005],tot,go[500005]; int fa[500005],ans[500005],V[1000005],n,m; void insert(int x,int y){tot++;go[tot]=y;next[tot]=first[x];first[x]=tot; } void add(int x,int v){for (int i=x;i<=hw;i+=(i)&(-i)){V[i]+=v;} } int query(int x){int res=0;for (int i=x;i;i-=(i)&(-i)){res+=V[i];}return res; } void build(){int now=1;sz=1;for (int i=0;i<n;i++){if (s[i]=='P') pos[++id]=now;elseif (s[i]=='B') now=fa[now];else{int k=s[i]-'a';if (ch[now][k]==0) ch[now][k]=++sz,fa[sz]=now;now=ch[now][k];}} } void bfs(){std::queue<int>Q;for (int i=0;i<26;i++)if (!ch[root][i]) ch[root][i]=root;else if (ch[root][i]){fail[ch[root][i]]=root;Q.push(ch[root][i]);}while (!Q.empty()){int now=Q.front();Q.pop();for (int i=0;i<26;i++)if (!ch[now][i]){ch[now][i]=ch[fail[now]][i];}else{fail[ch[now][i]]=ch[fail[now]][i];Q.push(ch[now][i]);}} } void dfs(int x){dfn[x]=++hw;for (int i=first[x];i;i=next[i]){int pur=go[i];dfs(pur);}low[x]=++hw; } void solve(){add(dfn[1],1);//root節點也算上 int sx=0,now=1;for (int i=0;i<n;i++){if (s[i]=='P'){sx++;for (int j=fi[sx];j;j=que[j].next){int pur=pos[que[j].to];ans[que[j].id]+=query(low[pur])-query(dfn[pur]-1);}//詢問dfs序區間里面有多少標記過的節點,有多少就代表y到root路徑上的節點有多少能走到x的尾節點 }elseif (s[i]=='B') add(dfn[now],-1),now=fa[now];//刪除的時候去掉 else{now=ch[now][s[i]-'a'];add(dfn[now],1);//走一步加一步 }} } int main(){scanf("%s",s);root=1;n=strlen(s);build();bfs();//建AC自動機 for (int i=1;i<=sz;i++)insert(fail[i],i);//建fail樹 dfs(0);//找dfs序 scanf("%d",&m);for (int i=1;i<=m;i++){//把y相同的詢問弄到一起 int x,y;scanf("%d%d",&x,&y);num++;que[num].to=x;que[num].next=fi[y];que[num].id=i;fi[y]=num;}solve();//統計答案 for (int i=1;i<=m;i++)printf("%d\n",ans[i]); }?
轉載于:https://www.cnblogs.com/qzqzgfy/p/5689086.html
總結
以上是生活随笔為你收集整理的BZOJ 2434 阿狸的打字机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android启动过程深入解析【转】
- 下一篇: php中的日期