【AC自动机-fail树+离线+DFS序+树状数组】BZOJ2434(Noi2011)[阿狸的打字机]题解
来源:互联网 发布:淘宝卖阿迪达斯的店铺 编辑:程序博客网 时间:2024/06/04 19:28
题目概述
有一台打字机,可以:
- 在字符串末尾插入一个小写字母。
- 删除字符串末尾的一个小写字母。
- 输出当前字符串。
还有
解题报告
观察打字的过程,我们发现这其实就是在构造一棵Trie:
- 在字符串末尾插入一个小写字母
→ 在当前节点now 扩展一个字符。 - 删除字符串末尾的一个小写字母
→ 将now 回退到父亲节点。
先按照打字顺序处理出Trie,然后构造好AC自动机和
所以我们可以用DFS序+树状数组来快速统计
既然如此我们考虑离线,先把所有与
- 在字符串末尾插入一个小写字母
→ 在当前节点now 扩展一个字符,将新的now 节点标记为1 。 - 删除字符串末尾的一个小写字母
→ 将now 节点标记为0 ,并回退到父亲节点。 - 输出当前字符串
→ 处理now 节点对应字符串y 的所有x ,答案为x 子树的权值和。
示例程序
代码有点乱……读者老爷凑合看看吧QAQ。
#include<cstdio>using namespace std;const int maxn=100000,maxm=100000,maxi=26;int n,te,ans[maxm+5];char s[maxn+5];int E,lnk[maxn+5],qlnk[maxn+5],nxt[maxn+maxm+5],chd[maxn+maxm+5],w[maxn+maxm+5];void Add(int x,int y) {chd[++E]=y;nxt[E]=lnk[x];lnk[x]=E;}void Add(int x,int y,int z) {chd[++E]=y;w[E]=z;nxt[E]=qlnk[x];qlnk[x]=E;}int si=1,son[maxn+5][maxi],top,stk[maxn+5],ID[maxn+5];int que[maxn+5],fai[maxn+5];void make_AC(){ top=0; for (int i=1;s[i];i++) if (s[i]=='B') top--; else if (s[i]=='P') ID[stk[top]]=++n; else { int &u=son[stk[top]][s[i]-'a'];if (!u) u=si++; stk[++top]=u; } int Head=0,Tail=0; for (int i=0;i<maxi;i++) if (son[0][i]) que[++Tail]=son[0][i],fai[son[0][i]]=0; while (Head!=Tail) { int x=que[++Head]; for (int i=0;i<maxi;i++) { if (!son[x][i]) {son[x][i]=son[fai[x]][i];continue;} int u=son[x][i];que[++Tail]=u;fai[u]=son[fai[x]][i]; } } for (int i=1;i<si;i++) Add(fai[i],i);}int ti,Lt[maxn+5],Rt[maxn+5],L[maxn+5],R[maxn+5];void Dfs(int x){ Lt[x]=++ti;if (ID[x]) L[ID[x]]=ti; for (int j=lnk[x];j;j=nxt[j]) Dfs(chd[j]); Rt[x]=ti;if (ID[x]) R[ID[x]]=ti;}int c[maxn+5];void Update(int x,int tem) {for (int p=x;p<=ti;p+=p&-p) c[p]+=tem;}int Sum(int x) {int sum=0;for (int p=x;p;p-=p&-p) sum+=c[p];return sum;}void Solve(){ top=0; for (int i=1;s[i];i++) if (s[i]=='B') Update(Lt[stk[top--]],-1); else if (s[i]=='P') { for (int j=qlnk[ID[stk[top]]];j;j=nxt[j]) ans[w[j]]=Sum(R[chd[j]])-Sum(L[chd[j]]-1); } else { top++;stk[top]=son[stk[top-1]][s[i]-'a']; Update(Lt[stk[top]],1); }}int main(){ freopen("program.in","r",stdin); freopen("program.out","w",stdout); scanf("%s%d",s+1,&te);make_AC(); for (int i=1;i<=te;i++) { int x,y;scanf("%d%d",&x,&y); Add(y,x,i); } Dfs(0);Solve(); for (int i=1;i<=te;i++) printf("%d\n",ans[i]); return 0;}
阅读全文
0 0
- 【AC自动机-fail树+离线+DFS序+树状数组】BZOJ2434(Noi2011)[阿狸的打字机]题解
- 【bzoj2434】[Noi2011]阿狸的打字机 AC自动机+fail树+dfs序+树状数组
- bzoj2434 [Noi2011]阿狸的打字机 ( AC自动机 & fail树 + 树状数组 + dfs序 )
- [BZOJ2434]NOI2011阿狸的打字机|AC自动机|fail树|树状数组
- BZOJ2434【NOI2011】阿狸的打字机 <AC自动机+Fail树+树状数组>
- BZOJ2434 [Noi2011]阿狸的打字机 【AC自动机 + fail树 + 树状数组】
- BZOJ2434 [Noi2011]阿狸的打字机【AC自动机+dfs序+树状数组】
- 【bzoj2434】【NOI2011】【阿狸的打字机】【AC自动机+dfs序+树状数组】
- bzoj2434(NOI2011).阿狸的打字机(AC自动机 && DFS序 && 树状数组)
- BZOJ 2434: [Noi2011]阿狸的打字机【AC自动机,fail树.dfs序,树状数组
- bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)
- bzoj2434 阿狸的打字机NOI2011ac自动机+fail树+树状数组+dfs序详解
- 【BZOJ】【P2434】【Noi2011】【阿狸的打字机】【题解】【fail树+dfs序+树状数组】
- [BZOJ2434][NOI2011]阿狸的打字机(AC自动机+树状数组)
- [BZOJ2434][NOI2011]阿狸的打字机(AC自动机+树状数组)
- [AC自动机 fail树 树状数组] BZOJ 2434 [NOI2011] 阿狸的打字机
- bzoj2434 ac自动机+fail树+Dfs序+树状数组
- 【BZOJ 2434】[Noi2011]阿狸的打字机 Ac自动机+树状数组+dfs序
- 微信小程序 高度占满整个屏幕
- Flex布局中的Flex-Grow无效问题
- IDEA和Eclipse修改注释模板
- java url正则表达式
- Jsoup介绍及解析常用方法
- 【AC自动机-fail树+离线+DFS序+树状数组】BZOJ2434(Noi2011)[阿狸的打字机]题解
- SpringBoot的RabbitMQ消息队列: 三、第二模式"Work queues"
- Vue常用经典开源项目汇总参考-海量
- JS中函数之外不能写return
- shell中 单引号、双引号、无引号、反斜杠在grep命令中的二次转义
- POJ 3723 Conscription
- @Transaction注解的理解以及手动回滚事务的2种方法
- oracle字段Varchar2长度问题
- jquery 用creatjs preloadjs的方法