BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机 fail树
来源:互联网 发布:淘宝借贷提前还款 编辑:程序博客网 时间:2024/06/08 10:34
一道AC自动机好题啊,做完了以后对AC自动机有了一个新的认识,首先由于这道题的特殊性我们无需一个一个字符串插入,只要维护一个father指针往回跳就行了,建好树了以后怎么办呢,我们可以想到A在AC自动机上是B的子串当且仅当B的节点跳fail指针可以跳到A,但是这样时间复杂度太大,由于fail指针总是由下向上指所以我们能想得到如果将fail倒过来那么将形成一颗树,我们称之为fail树,那么B的节点跳fail能跳到A等价于B的节点在A的子树中,我们只需维护A的子树中有多少B的节点就好了,我们只要维护一下dfs序就可快速得知子树信息,用树状数组就可以区间求和,由于这道题的特殊性,将询问按照y值排序,我们只需再跑一边字符串就可nlogn维护树状数组,这样这道题就解决了
1A ^_^
#include<cstdio>#include<cstdlib>#include<iostream>#include<iomanip>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>using namespace std;struct Trie{ Trie *son[26],*fail,*fa; int num; int wz; Trie() { memset(son,0,sizeof(son)); fa=fail=NULL; num=0; }}mempool[1000000],*root=&mempool[0];int toppp=0;int top=0;void my_insert(char *s){ root->fa=root; Trie *o=root; while(*s) { if(*s=='B') o=o->fa; else if(*s=='P') o->num=++top; else { if(!o->son[*s-'a']) { o->son[*s-'a']=&mempool[++toppp]; o->son[*s-'a']->fa=o; } o=o->son[*s-'a']; } s++; }}struct edge{ int l,r;}a[1000000];int fir[1000000];int nex[1000000];int tot=0;void add_edge(int l,int r){ a[++tot].l=l; a[tot].r=r; nex[tot]=fir[l]; fir[l]=tot;}void bfs(){ static Trie* dui[1000000]; int top=1,my_final=1; for(int i=0;i<26;i++) { if(root->son[i]) { root->son[i]->fail=root; add_edge(root->wz,root->son[i]->wz); dui[my_final++]=root->son[i]; } else root->son[i]=root; } while(top<my_final) { Trie *o=dui[top++]; for(int i=0;i<26;i++) { if(o->son[i]) { dui[my_final++]=o->son[i]; o->son[i]->fail=o->fail->son[i]; add_edge(o->fail->son[i]->wz,o->son[i]->wz); } else o->son[i]=o->fail->son[i]; } }}int dfsx[1000000];int wz[1000000];int tott=0;int my_begin[1000000];int my_end[1000000];int c[1000000];int mapp[1000000];void dfs(int u,int from){ dfsx[++tott]=u; my_begin[u]=tott; if(mempool[u].num) mapp[mempool[u].num]=u; for(int o=fir[u];o!=0;o=nex[o]) if(a[o].r!=from) dfs(a[o].r,u); dfsx[++tott]=u; my_end[u]=tott;}struct query{ int x,y,num; bool operator <(query b) const { return y<b.y; }}queries[1000000];int ans[1000000];inline void add_v(int x,int v){ for(int i=x;i<=tott;i+=i&-i) c[i]+=v;}inline int my_search(int l,int r){ int re=0; for(int i=r;i;i-=i&-i) re+=c[i]; for(int i=l-1;i;i-=i&-i) re-=c[i]; return re;}int pipei=1;void search_ans(char *s){ Trie *o=root; add_v(my_begin[root->wz],1); while(*s) { if(*s=='B') { add_v(my_begin[o->wz],-1); o=o->fa; } else if(*s=='P') { while(queries[pipei].y==o->num) { ans[queries[pipei].num]=my_search(my_begin[mapp[queries[pipei].x]],my_end[mapp[queries[pipei].x]]); pipei++; } } else { o=o->son[*s-'a']; add_v(my_begin[o->wz],1); } s++; }}char s[1000000];int main(){ scanf("%s",s); my_insert(s); for(int i=0;i<=toppp;i++) mempool[i].wz=i; bfs(); dfs(0,-1); int m; scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%d%d",&queries[i].x,&queries[i].y),queries[i].num=i; sort(queries+1,queries+1+m); search_ans(s); for(int i=1;i<=m;i++) { printf("%d\n",ans[i]); }}
1 1
- BZOJ 2434([Noi2011]阿狸的打字机-AC自动机-Fail树)
- [AC自动机 fail树 树状数组] BZOJ 2434 [NOI2011] 阿狸的打字机
- BZOJ 2434: [Noi2011]阿狸的打字机【AC自动机,fail树.dfs序,树状数组
- BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机 fail树
- bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)
- bzoj 2434 阿狸的打字机 AC自动机+fail树
- 【AC自动机】 BZOJ 2434 [Noi2011]阿狸的打字机
- BZOJ 2434 [Noi2011] 阿狸的打字机 Fail树
- [BZOJ2434]NOI2011阿狸的打字机|AC自动机|fail树|树状数组
- 【bzoj2434】[Noi2011]阿狸的打字机 AC自动机+fail树+dfs序+树状数组
- 【AC自动机-fail树+离线+DFS序+树状数组】BZOJ2434(Noi2011)[阿狸的打字机]题解
- BZOJ2434【NOI2011】阿狸的打字机 <AC自动机+Fail树+树状数组>
- bzoj2434 [Noi2011]阿狸的打字机 ( AC自动机 & fail树 + 树状数组 + dfs序 )
- BZOJ2434 [Noi2011]阿狸的打字机 【AC自动机 + fail树 + 树状数组】
- 【AC自动机】[NOI2011]阿狸的打字机
- BZOJ 2434 NOI 2011 阿狸的打字机 AC自动机构造fail树
- [BZOJ]2434 阿狸的打字机 AC自动机+Fail树+树状数组
- BZOJ 2434 阿狸的打字机 (AC自动机 fail树 树状数组)
- Objective-c - 继承的本质, new方法
- jQuery 效果- 动画
- jQuery的tabs
- jQuery 停止动画
- jQuery Callback 方法
- BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机 fail树
- ZCMU—1111
- 微信小程序产品定位及功能介绍
- Android Binder机制浅析
- system()
- c语言中定义的数组按照指定字节对齐
- tomcat的虚拟路径,访问服务器外指定路径下的静态资源,如图片、视频等
- jQuery - 链(Chaining)
- 总结一下目前为止碰到的Python编译错误