bzoj 2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
来源:互联网 发布:wow7.0优化 编辑:程序博客网 时间:2024/06/05 15:00
题意
给你一棵trie,每次询问一个串在另一个串中出现了多少次。
n,q<=100000
分析
好气啊骑士队居然输掉了!!!不过老詹还是很给力的啊。气得我都不想写题了。
首先很显然这是一棵trie。
考虑朴素的做法,可以每次把两个串进行匹配,复杂度是O(qn^2)。考虑用AC自动机的fail指针来优化,可以做到O(nq),但仍然会超时。
显然一个串s1在另一个串s2中出现的次数就等于根到s2的结尾中有多少个节点可以通过fail指针到达s1所在节点。因为每个点的fail指针只会指向另一个点,所以我们把所有fail指针反向,这就变成了一棵fail树。显然若i为j的祖先,那么j就可以通过fail指针走到i。
那么现在就好做很多了。考虑其中一个询问(s1,s2),其答案就等于fail树中s1所在节点的子树内有多少个节点是s2串上的节点。
考虑把询问离线,用邻接表记录每个串的询问,然后求出fail树的dfs序。然后最后dfs的时候,每到达一个点就将其dfs序加入树状数组中,退出的时候就扔出来。这样每到达一个串,树状数组中储存的就是这个串所包含的节点,那么就可以O(log)回答每个询问了。
在本地和luogu上都过了,但不知道为啥在bzoj上就是A不了2333
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<stack>#include<queue>#include<vector>using namespace std;const int N=100005;int len,m,cnt,sz,ls[N],last[N],fail[N],dfn[N],c[N],ch[N][26],tim,mn[N],mx[N],ans[N],tot,id[N];struct edge{int to,next;}e[N],q[N];queue<int> que;stack<int> sta;vector<int> vec[N];char str[N];void addedge(int u,int v){ if (u==v) return; e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;}void build(){ int now=0;sta.push(0); for (int i=1;i<=len;i++) if (str[i]=='P') vec[now].push_back(++tot),id[tot]=now; else if (str[i]=='B') sta.pop(),now=sta.top(); else if (!ch[now][str[i]-'a']) ch[now][str[i]-'a']=now=++sz,sta.push(sz); else now=ch[now][str[i]-'a'],sta.push(now); for (int i=0;i<26;i++) if (ch[0][i]) que.push(ch[0][i]); while (!que.empty()) { int u=que.front();que.pop(); for (int i=0;i<26;i++) if (ch[u][i]) { int v=ch[u][i],k=fail[u];que.push(v); while (k&&!ch[k][i]) k=fail[k]; fail[v]=ch[k][i]; } addedge(fail[u],u); }}void dfs(int x){ dfn[x]=mn[x]=++tim; for (int i=last[x];i;i=e[i].next) dfs(e[i].to); mx[x]=tim;}void ins(int x,int y){ while (x<=tim) c[x]+=y,x+=x&(-x);}int query(int x){ int ans=0; while (x) ans+=c[x],x-=x&(-x); return ans;}void solve(int x){ ins(dfn[x],1); if (!vec[x].empty()) { for (vector<int>::iterator it=vec[x].begin();it!=vec[x].end();it++) { int now=*it; for (int i=ls[now];i;i=q[i].next) ans[i]=query(mx[id[q[i].to]])-query(mn[id[q[i].to]]-1); } } for (int i=0;i<26;i++) if (ch[x][i]) solve(ch[x][i]); ins(dfn[x],-1);}int main(){ scanf("%s",str+1); len=strlen(str+1); build(); dfs(0); scanf("%d",&m); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); q[i].to=x;q[i].next=ls[y];ls[y]=i; } solve(0); for (int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0;}
阅读全文
0 0
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
- bzoj 2434 [Noi2011]阿狸的打字机 [AC自动机+树状数组]
- [AC自动机 fail树 树状数组] BZOJ 2434 [NOI2011] 阿狸的打字机
- BZOJ 2434: [Noi2011]阿狸的打字机【AC自动机,fail树.dfs序,树状数组
- 【BZOJ 2434】[Noi2011]阿狸的打字机 Ac自动机+树状数组+dfs序
- bzoj 2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
- bzoj 2434 (NOI2011)阿狸的打字机 【AC自动机】【树状数组】【DFS序】
- [BZOJ]2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
- bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)
- ★【AC自动机】【树状数组】【NOI2011】阿狸的打字机
- [NOI2011]阿狸的打字机(AC自动机+树状数组)
- BZOJ 2434 阿狸的打字机 (AC自动机 + 树状数组)
- 【AC自动机】 BZOJ 2434 [Noi2011]阿狸的打字机
- [BZOJ2434]NOI2011阿狸的打字机|AC自动机|fail树|树状数组
- BZOJ2434 [Noi2011]阿狸的打字机【AC自动机+dfs序+树状数组】
- 【bzoj2434】[Noi2011]阿狸的打字机 AC自动机+fail树+dfs序+树状数组
- [BZOJ2434][NOI2011]阿狸的打字机(AC自动机+树状数组)
- 【bzoj2434】【NOI2011】【阿狸的打字机】【AC自动机+dfs序+树状数组】
- 机器学习算法实现解析——libFM之libFM的训练过程概述
- [YTU]_2624( B 结构体--统计投票)
- Neither BindingResult nor plain target object for bean name 'sqmy' available as request attribute
- LeetCode Algorithms 233. Number of Digit One 题解
- eclipse安装maven时,pom.xml提示报错
- bzoj 2434: [Noi2011]阿狸的打字机 AC自动机+树状数组
- Zynq Emacps Linux Driver
- kivy textinput弹出输入框处理
- 设计模式学习:工厂模式
- springboot的三种启动方式
- 使用SfntTool制作字体剪辑工具1
- ssM框架简单配置文件
- 蓝桥杯 BASIC-26 基础练习 报时助手
- 机器学习算法实现解析——libFM之libFM的训练过程之SGD的方法