[BZOJ 2434][Noi2011]阿狸的打字机(AC自动机+树状数组+dfs序)
Description
打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。经阿狸研究发现,这个打字机是这样工作的:
·输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
·按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。
·按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
例如,阿狸输入aPaPBbP,纸上被打印的字符如下:
a aa ab 我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。
阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?
Solution
居然1A【然而看了题解】
查询x在y中出现了多少次,即y的节点有多少可以通过fail跳到x的尾节点
但是这个太暴力了,于是我们建一下fail树(fail的反向边,由fail指针指向原节点)
转化为查询x的尾节点可以从fail树到达的y的节点有多少个
然后就可以通过dfs序和树状数组做了
离线,对于相同的y一次性处理,标记出所有y的节点,查询每一个x的子树中y的节点的出现次数
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> #define MAXN 100005 using namespace std; int m,sz,root,pos[MAXN],in[MAXN],out[MAXN],dfn_clock=0,c[MAXN],ans[MAXN],dfn[MAXN]; int head1[MAXN],head2[MAXN],cnt1=0,cnt2=0; struct Node2 {int next,to; }e1[MAXN],e2[MAXN]; void addedge1(int u,int v) {e1[++cnt1].next=head1[u];head1[u]=cnt1;e1[cnt1].to=v; } void addedge2(int u,int v) {e2[++cnt2].next=head2[u];head2[u]=cnt2;e2[cnt2].to=v; } char s[MAXN]; struct Node1 {int next[26],par,fail; }trie[MAXN]; int newnode(int f) {trie[++sz].fail=0;trie[sz].par=f;memset(trie[sz].next,0,sizeof(trie[sz].next));return sz; } void insert() {sz=0,root=newnode(0);int i=0,p=root,_clock=0;while(s[i]){if(s[i]=='B')p=trie[p].par;else if(s[i]=='P')pos[++_clock]=p;else {int idx=s[i]-'a';if(!trie[p].next[idx])trie[p].next[idx]=newnode(p);p=trie[p].next[idx];}i++;} } queue<int>q; void build() {q.push(root);while(!q.empty()){int p=q.front();q.pop();for(int i=0;i<26;i++){int t=trie[p].fail;while(t&&!trie[t].next[i])t=trie[t].fail;if(trie[p].next[i]){trie[trie[p].next[i]].fail=t?trie[t].next[i]:root;q.push(trie[p].next[i]);}else trie[p].next[i]=t?trie[t].next[i]:root;}} } void dfs(int u) {if(dfn[u])return; ++dfn_clock;in[u]=dfn[u]=dfn_clock;for(int i=head1[u];~i;i=e1[i].next)dfs(e1[i].to);out[u]=dfn_clock; } int lowbit(int x){return x&(-x);} void add(int x,int p) {while(p<=sz+1){c[p]+=x;p+=lowbit(p);} } int query(int p) {int res=0;while(p>0){res+=c[p];p-=lowbit(p);}return res; } void solve() {int i=0,p=root,_clock=0;while(s[i]){if(s[i]=='B')add(-1,dfn[p]),p=trie[p].par;else if(s[i]=='P'){++_clock;for(int j=head2[_clock];~j;j=e2[j].next){int t=e2[j].to;ans[j]=query(out[pos[t]])-query(in[pos[t]]-1);}}else{int idx=s[i]-'a';p=trie[p].next[idx];add(1,dfn[p]);}i++;} } int main() {memset(head1,-1,sizeof(head1));memset(head2,-1,sizeof(head2));scanf("%s",s); insert(),build();for(int i=1;i<=sz;i++)addedge1(trie[i].fail,i);scanf("%d",&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);addedge2(y,x);}dfs(0);solve();for(int i=1;i<=m;i++)printf("%d\n",ans[i]);return 0; }
转载于:https://www.cnblogs.com/Zars19/p/6817784.html
[BZOJ 2434][Noi2011]阿狸的打字机(AC自动机+树状数组+dfs序)相关推荐
- BZOJ 2434 NOI2011阿狸的打字机 AC自动机+树状数组
如果你还没学AC自动机,请看这篇博客 Problem bzoj通道 洛谷通道 Solution 简单的说来,其实就是要快速求一个字符串在另一个字符串中出现了多少次.考虑构造AC自动机. 首先可以想到很 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 2545 Solved: 1419 [Submit][S ...
- 【bzoj2434】阿狸的打字机 AC自动机+树状数组
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题解] 这是一道很神的题. 先建一个AC自动机,这里需要维护一下父结点,以便删除时 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 ACAM+fail树
title BZOJ 2434 LUOGU 2414 Description 打字机上只有 \(28\) 个按键,分别印有 \(26\) 个小写英文字母和 B.P 两个字母,是这样工作的: 输入小写字 ...
- bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 3521 Solved: 1913 [Submit][S ...
- [bzoj 2434][Noi2011]阿狸的打字机
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory ...
- BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 我写的是离线做法,不知道有没有在线做法. 转化一波题意,\(x\)在AC ...
- bzoj 2434: [Noi2011]阿狸的打字机
题意: 给出一个字典树,并告诉你若干串的结束位置.求第x个串在第y个串的出现次数. 题解: 不难的AC自动机+不难的主席树. 首先对于字典树建AC自动机,那么对于一个串S,假如能在这个串的结尾点不断跳 ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
最新文章
- ffmpeg php 快速播放,怎么在PHP中利用FFmpeg函数对视频播放的时长进行获取
- java SSM 框架 多数据源 代码生成器 websocket即时通讯 shiro redis 后台框架源码
- 全球及中国一次性造口袋行业发展前景预测及投资价值分析报告2021-2027年版
- C++设计模式之代理模式
- mysql基本的增删改查和条件语句
- 应用程序缓存_应用程序模块和实体缓存
- 允许指定IP访问远程桌面
- 某大型银行深化系统技术方案之十一:核心层之业务活动监控
- 读取图像中任意点的像素值
- 开启Hive的本地模式
- Android动态生成答题卡,好分数怎样制作答题卡
- 小白学习cartopy气象画地图的第二天(中国区域,陆地温度分布图)
- 理论 - 半波偶极子天线原理与计算
- 谷歌翻译函数C#代码实现
- 电磁波,无线电,Wifi 4G,摩擦生电
- PS制作简单可爱马赛克像素画效果
- 木马是如何穿过防火墙的
- Linux安装mysql没有my.cnf文件
- iframe嵌入通讯
- 2021年植发行业研究报告
热门文章
- 优酷开放SDK之setOnCompletionListener
- dbcc dbreindex server sql_DBCC DBREINDEX重建索引提高SQL Server性能
- OGNL表达式struts2标签“%,#,$”
- 深入理解connect by
- spring 中 Hibernate 事务和JDBC事务嵌套问题
- Blueprint 使用手记
- SCA (Service Component Architecture)
- hibernate异常:not-null property references a null or transient value
- vue/cli 3.0 脚手架【进阶】 使用 amfe-flexible 和 postcss-px2rem进行移动端适
- 黑马java代码04-05.docx