【NOI2011】 阿狸的打字机(AC自动机+树状数组)

这篇博客介绍了如何使用AC自动机和树状数组来解决字符串子串出现次数的问题。阿狸的打字机问题作为例子,解释了输入输出格式,以及如何通过AC自动机构建 Trie 树,并利用树状数组维护子串出现次数的前缀和,从而达到高效查询的目的。

题意

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

经阿狸研究发现,这个打字机是这样工作的:

  • 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。

  • 按一下印有’B’的按键,打字机凹槽中最后一个字母会消失。

  • 按一下印有’P’的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。

例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

a

aa

ab

我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其 中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

输入格式

输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。

第二行包含一个整数 m,表示询问个数。

接下来 m 行描述所有由小键盘输入的询问。其中第 i 行包含两个整数 x, y,表示第 i 个询问为 (x, y)。

输出格式

输出 m 行,其中第 i 行包含一个整数,表示第 i 个询问的答案。

输入输出样例
输入 #1

aPaPBbP
3
1 2
1 3
2 3

输出 #1

2
1
0

分析

感觉自己字符串题只会依赖哈希很丢人,于是去学了 KMP 和 AC自动机,然后开了这题。。
现在假设我们建完了 AC自动机。
首先我们看一下 xxxyyy 的子串的条件是什么,其实是存在 yyy 的某个节点,它沿着 failfailfail 指针一直跳,能跳到 xxx 的末节点(其实就是 xxxyyy 某个前缀的后缀)。
xxxyyy 中的出现次数,其实就是 yyy 的所有节点中,以 xxx 为后缀的节点数,这些节点都可以通过跳 failfailfail 跳到 xxx 的末节点。
不妨把 failfailfail 指针和 trietrietrie 树的所有节点看成一颗树,那么所有能跳到 xxx 的点都在 xxx 的子树中。
现在的问题就转化为:xxx 的子树中,有多少个点属于 yyy
我们把属于 yyy 的点记为 111,那么答案就是 xxx 的子树和。
子树和,其实就是 dfsdfsdfs 序上的前缀和。

然后考虑建 trietrietrie 树的过程:

  • BBB 相当于跳到父节点
  • PPP 相当于新打印出一个字符串
  • 其他就是正常建 trietrietrie

这样子,trietrietrie 的形态一直都是一条链。
我们考虑离线,求 yy

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值