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序)相关推荐

  1. BZOJ 2434 NOI2011阿狸的打字机 AC自动机+树状数组

    如果你还没学AC自动机,请看这篇博客 Problem bzoj通道 洛谷通道 Solution 简单的说来,其实就是要快速求一个字符串在另一个字符串中出现了多少次.考虑构造AC自动机. 首先可以想到很 ...

  2. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2545  Solved: 1419 [Submit][S ...

  3. 【bzoj2434】阿狸的打字机 AC自动机+树状数组

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题解] 这是一道很神的题. 先建一个AC自动机,这里需要维护一下父结点,以便删除时 ...

  4. BZOJ 2434: [Noi2011]阿狸的打字机 ACAM+fail树

    title BZOJ 2434 LUOGU 2414 Description 打字机上只有 \(28\) 个按键,分别印有 \(26\) 个小写英文字母和 B.P 两个字母,是这样工作的: 输入小写字 ...

  5. bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3521  Solved: 1913 [Submit][S ...

  6. [bzoj 2434][Noi2011]阿狸的打字机

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory ...

  7. BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 我写的是离线做法,不知道有没有在线做法. 转化一波题意,\(x\)在AC ...

  8. bzoj 2434: [Noi2011]阿狸的打字机

    题意: 给出一个字典树,并告诉你若干串的结束位置.求第x个串在第y个串的出现次数. 题解: 不难的AC自动机+不难的主席树. 首先对于字典树建AC自动机,那么对于一个串S,假如能在这个串的结尾点不断跳 ...

  9. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

    [BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...

最新文章

  1. ffmpeg php 快速播放,怎么在PHP中利用FFmpeg函数对视频播放的时长进行获取
  2. java SSM 框架 多数据源 代码生成器 websocket即时通讯 shiro redis 后台框架源码
  3. 全球及中国一次性造口袋行业发展前景预测及投资价值分析报告2021-2027年版
  4. C++设计模式之代理模式
  5. mysql基本的增删改查和条件语句
  6. 应用程序缓存_应用程序模块和实体缓存
  7. 允许指定IP访问远程桌面
  8. 某大型银行深化系统技术方案之十一:核心层之业务活动监控
  9. 读取图像中任意点的像素值
  10. 开启Hive的本地模式
  11. Android动态生成答题卡,好分数怎样制作答题卡
  12. 小白学习cartopy气象画地图的第二天(中国区域,陆地温度分布图)
  13. 理论 - 半波偶极子天线原理与计算
  14. 谷歌翻译函数C#代码实现
  15. 电磁波,无线电,Wifi 4G,摩擦生电
  16. PS制作简单可爱马赛克像素画效果
  17. 木马是如何穿过防火墙的
  18. Linux安装mysql没有my.cnf文件
  19. iframe嵌入通讯
  20. 2021年植发行业研究报告

热门文章

  1. 优酷开放SDK之setOnCompletionListener
  2. dbcc dbreindex server sql_DBCC DBREINDEX重建索引提高SQL Server性能
  3. OGNL表达式struts2标签“%,#,$”
  4. 深入理解connect by
  5. spring 中 Hibernate 事务和JDBC事务嵌套问题
  6. Blueprint 使用手记
  7. SCA (Service Component Architecture)
  8. hibernate异常:not-null property references a null or transient value
  9. vue/cli 3.0 脚手架【进阶】 使用 amfe-flexible 和 postcss-px2rem进行移动端适
  10. 黑马java代码04-05.docx