[JZOJ2784][BZOJ2434]【NOI2011】阿狸的打字机
来源:互联网 发布:php画三角形星星 编辑:程序博客网 时间:2024/05/18 01:46
Description
阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有 26个小写英文字母和’B’、’P’两个字母。 经阿狸研究发现,这个打字机是这样工作的:
输入小写字母,打字机的一个凹槽中会加入这个字母(按 P 前凹槽中至少有一个字母)。
按一下印有’B’的按键,打字机凹槽中最后一个字母会消失。
按一下印有’P’的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失(保证凹槽中至少有一个字母) 。
例如,阿狸输入 aPaPBbP,纸上被打印的字符如下:
a
aa
ab
我们把纸上打印出来的字符串从 1开始顺序编号,一直到 n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。 阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?
1≤n≤ 10^5
1≤m≤ 10^5
输入文件第一行的字符数≤10^5
Solution
先将AC自动机构出来,同时构出fail树
可以发现,一个点所代表的串,一定都在这个点在fail树上的子树内的所有点所代表的字符串出现过。
那么对于一个询问(x,y)只需要统计x在fail树上的子树中包含了y的路径上的多少个点
可以把所有询问挂在它们的y上
子树统计可以用树状数组维护fail树的DFS序
那么构完以后重新扫一遍字符串,相应的在Trie上跑,遇到P就统计,遇到B就在树桩树组中删掉对应的,并且跳到它在Trie上的父亲,遇到字母就相应加入树状数组
复杂度
Code
#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <vector>#define N 200005#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)using namespace std;int n,n1,m1,fail[N],fs[N],nt[N],dt[N],m,t[N][26],c[N],pt[N],fa[N],lx[N],rx[N],d[N],vl[N],dfn[N],df[N],le[N],qs[N][2],ans[N];vector<int> ask[N];char ch[N];void link(int x,int y){ nt[++m1]=fs[x]; dt[fs[x]=m1]=y;}void dfs(int k){ dfn[++dfn[0]]=k,lx[k]=dfn[0],df[k]=dfn[0]; for(int i=fs[k];i;i=nt[i]) dfs(dt[i]); rx[k]=dfn[0];}void prp(){ int l=0,r=1; d[1]=1,fail[1]=0; while(l<r) { int k=d[++l]; fo(i,0,25) { int p=t[k][i]; if(p>0) { d[++r]=p; if(k==1) fail[p]=1,link(1,p); else { fail[p]=fail[k]; while(fail[p]>1&&t[fail[p]][vl[p]]==0) fail[p]=fail[fail[p]]; if(t[fail[p]][vl[p]]) fail[p]=t[fail[p]][vl[p]]; link(fail[p],p); } } } }}int lowbit(int k){ return (k&(-k));}int get(int k){ int s=0; while(k) s+=c[k],k-=lowbit(k); return s;}void put(int k,int v){ while(k<=n1) c[k]+=v,k+=lowbit(k);}int main(){ scanf("%s",ch+1); n=strlen(ch+1); n1=1; int k=1; fo(i,1,n) { if(ch[i]=='B') k=fa[k]; else if(ch[i]=='P') pt[++m]=k; else { if(!t[k][ch[i]-'a']) t[k][ch[i]-'a']=++n1,fa[n1]=k; k=t[k][ch[i]-'a']; vl[k]=ch[i]-'a'; } } prp(); dfs(1); int q; cin>>q; fo(i,1,q) { scanf("%d%d",&qs[i][0],&qs[i][1]); ask[pt[qs[i][1]]].push_back(i),le[pt[qs[i][1]]]++; } k=1; fo(i,1,n) { if(ch[i]=='B') put(df[k],-1),k=fa[k]; else if(ch[i]=='P') { fo(j,0,le[k]-1) { int x=ask[k][j]; ans[x]=get(rx[pt[qs[x][0]]])-get(lx[pt[qs[x][0]]]-1); } } else { k=t[k][ch[i]-'a']; put(df[k],1); } } fo(i,1,q) printf("%d\n",ans[i]);}
- [JZOJ2784][BZOJ2434]【NOI2011】阿狸的打字机
- [NOI2011][JZOJ2784]阿狸的打字机
- bzoj2434: [Noi2011]阿狸的打字机
- [BZOJ2434][NOI2011]阿狸的打字机
- bzoj2434 阿狸的打字机 noi2011
- bzoj2434: [Noi2011]阿狸的打字机
- bzoj2434【NOI2011】阿狸的打字机
- bzoj2434: [Noi2011]阿狸的打字机
- BZOJ2434: [Noi2011]阿狸的打字机
- bzoj2434 [Noi2011]阿狸的打字机
- 【NOI2011】bzoj2434 阿狸的打字机
- NOI2011 阿狸的打字机(BZOJ2434) 题解
- 【BZOJ2434】【NOI2011】阿狸的打字机 AC自动机
- bzoj2434: [Noi2011]阿狸的打字机 trie+线段树
- fail树 【Noi2011】 阿狸的打字机 bzoj2434
- [BZOJ2434][NOI2011]阿狸的打字机-AC自动机
- BZOJ2434 NOI2011 洛谷2414 阿狸的打字机
- bzoj2434 阿狸的打字机
- spring cloud之zuul路由网关(六)
- 导出Excel
- 知识点累计
- 树的遍历及应用
- Android View的工作流程
- [JZOJ2784][BZOJ2434]【NOI2011】阿狸的打字机
- 一.Zookeeper三节点集群环境搭建(centOS)
- Constraint Layout(二)--添加和调整元素
- JS获取当前时间戳的方法
- Linux Kettle 闪退问题解决方案
- weblogic怎么修改长长的项目名访问
- npm修改源
- db2数据迁移到oracle
- 设计模式--Observer(转自k_eckel)