题意

阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有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自动机。
首先我们看一下 xxx 是 yyy 的子串的条件是什么,其实是存在 yyy 的某个节点,它沿着 failfailfail 指针一直跳,能跳到 xxx 的末节点(其实就是 xxx 是 yyy 某个前缀的后缀)。
xxx 在 yyy 中的出现次数,其实就是 yyy 的所有节点中,以 xxx 为后缀的节点数,这些节点都可以通过跳 failfailfail 跳到 xxx 的末节点。
不妨把 failfailfail 指针和 trietrietrie 树的所有节点看成一颗树,那么所有能跳到 xxx 的点都在 xxx 的子树中。
现在的问题就转化为:xxx 的子树中,有多少个点属于 yyy。
我们把属于 yyy 的点记为 111,那么答案就是 xxx 的子树和。
子树和,其实就是 dfsdfsdfs 序上的前缀和。

然后考虑建 trietrietrie 树的过程:

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

这样子,trietrietrie 的形态一直都是一条链。
我们考虑离线,求 yyy 作为询问串时 xxx 的出现次数。
那么我们在搞 trietrietrie 的时候:

  • 遇到 BBB,在 dfnpdfn_pdfnp​ 处 −1-1−1,然后 p=fapp=fa_pp=fap​
  • 遇到 PPP,说明此时节点为一个字符串 yyy 的结束,处理所有询问
  • 对于其他,在 dfnpdfn_pdfnp​ 处 +1+1+1

这样对于每一个询问 xxx,我们只用看 xxx 的子树和,然后用树状数组可以快速维护前缀和。
复杂度 O(qlogn)O(qlogn)O(qlogn)。

代码如下

#include <bits/stdc++.h>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#define m_p make_pair
#define N 100005
using namespace __gnu_pbds;
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
struct custom_hash {static uint64_t splitmix64(uint64_t x) {x += 0x9e3779b97f4a7c15;x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;x = (x ^ (x >> 27)) * 0x94d049bb133111eb;return x ^ (x >> 31);}size_t operator()(uint64_t x) const {static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();return splitmix64(x + FIXED_RANDOM);}
};
LL z = 1;
int read(){int x, f = 1;char ch;while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;x = ch - '0';while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;return x * f;
}
int ksm(int a, int b, int p){int s = 1;while(b){if(b & 1) s = z * s * a % p;a = z * a * a % p;b >>= 1;}return s;
}
int ch[N][26], Q[N], h[N], fa[N], v[N], c[N], fail[N], l[N], r[N], ans[N], dfn, cnt, tot, ret;
char s[N];
vector<pair<int, int> > q[N];
struct node{int a, b, n;
}d[N * 2];
void add(int i, int x){for(; i <= 100000; i += i&-i) c[i] += x;
}
int query(int i){int s = 0;for(; i > 0; i -= i&-i) s += c[i];return s;
}
void cr(int a, int b){d[++cnt].a = a; d[cnt].b = b; d[cnt].n = h[a]; h[a] = cnt;
}
void insert(char *s){int i, c, n = strlen(s), p = 0;for(i = 0; i < n; i++){if(s[i] == 'P') Q[++ret] = p;else if(s[i] == 'B') p = fa[p];else{c = s[i] - 'a';if(!ch[p][c]) ch[p][c] = ++tot, fa[tot] = p;p = ch[p][c];}}
}
void get_fail(){queue<int> q;int i, a, j;for(i = 0; i < 26; i++) if(ch[0][i]) q.push(ch[0][i]);while(!q.empty()){a = q.front(); q.pop();for(i = 0; i < 26; i++){if(ch[a][i]) fail[ch[a][i]] = ch[fail[a]][i], q.push(ch[a][i]);else ch[a][i] = ch[fail[a]][i];}}
}
void dfs(int a, int f){int i, b;l[a] = ++dfn;for(i = h[a]; i; i = d[i].n){b = d[i].b;if(b == f) continue;dfs(b, a);}r[a] = dfn;
}
void work(char *s){int i, j, c, n, p = 0, ret = 0, x, id;n = strlen(s);for(i = 0; i < n; i++){if(s[i] == 'P'){ret++;for(auto t: q[ret]){x = Q[t.first]; id = t.second;ans[id] = query(r[x]) - query(l[x] - 1);}}else if(s[i] == 'B') add(l[p], -1), p = fa[p];else{c = s[i] - 'a';if(!ch[p][c]) ch[p][c] = ++tot, fa[tot] = p;p = ch[p][c];add(l[p], 1);}}
}
int main(){int i, j, n, m, x, y;scanf("%s", s);insert(s);get_fail();for(i = 1; i <= tot; i++) cr(fail[i], i);dfs(0, 0);m = read();for(i = 1; i <= m; i++){x = read(); y = read();q[y].push_back(m_p(x, i));}memset(ch, 0, sizeof(ch));memset(fa, 0, sizeof(fa));tot = 0;work(s);for(i = 1; i <= m; i++) printf("%d\n", ans[i]);return 0;
}

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

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

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

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

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

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

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

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

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

  5. 【bzoj2434】[Noi2011]阿狸的打字机 AC自动机+Dfs序+树状数组

    题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小 ...

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

    Description 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: ·输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母 ...

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

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

  8. P2414 NOI2011阿狸的打字机 [AC自动机,dfs序]

    阿狸的打字机 题解 题目中给出的字符串就是构建TrieTrieTrie树的顺序.我们将字符串依次读入,每读入一个小写字符就相当于在TrieTrieTrie树当前节点下插入一个小写字符,读入BBB时,就 ...

  9. P2414-[NOI2011]阿狸的打字机【AC自动机,树状数组】

    正题 题目链接:https://www.luogu.com.cn/problem/P2414 题目大意 一个子串表示操作有 往凹槽里打一个字母 删除最后一个字母 将凹槽中的字母打印到一个新的行里(原来 ...

  10. 「模拟赛20180306」回忆树 memory LCA+KMP+AC自动机+树状数组

    题目描述 回忆树是一棵树,树边上有小写字母. 一次回忆是这样的:你想起过往,触及心底--唔,不对,我们要说题目. 这题中我们认为回忆是这样的:给定 \(2\) 个点 \(u,v\) (\(u\) 可能 ...

最新文章

  1. 373. Find K Pairs with Smallest Sums (java,优先队列)
  2. kali 更新源_kali安装避坑
  3. mysql 水平拆分实例_2021先定个小目标?搞清楚MyCat分片的两种拆分方法和分片规则!(二):水平拆分实例解析和代码实现!...
  4. 你最近学到的 飞鸽传书 东西的题目
  5. 实时体积云渲染(地平线):一.云的生成
  6. SQL里变量的声明以及常用函数举例
  7. Windows下配置Git
  8. VS项目打包,并自动安装SQL数据库
  9. 西瓜书《机器学习》线性模型 一元线性回归公式推导
  10. JAVA day20、21 双列集合Map<K,V>:HashMap,LinkedHashMap,TreeMap,Hashtable, ConcurrentHashMap;JDK1.9新特性
  11. php 获取src,html-使用PHP获取img src
  12. java WebSocket客户端断线重连 | 实用代码框架
  13. 外接键盘Win键不能的使用问题以及FN键的使用
  14. 基线管理之Windows安全配置
  15. win10 outlook2016 如何删除IMAP文件夹 (脑残党操作)
  16. 阿里一p7员工为了证明自己确实年入百万,晒出了他的工资
  17. 【详解】为何三元一次方程可以表示一个平面
  18. 本地推送jar包到远程maven仓库
  19. Python视觉摄像头检测有趣项目之机器学习和概率论重点概念分析重要(三)(重点)
  20. 计算机专业毕业实习心得

热门文章

  1. 计算机二级msoffice高级应用代码,计算机等级考试二级
  2. [转载]淘宝技术发展
  3. 有哪些因素会淘宝的宝贝突然没有流量?
  4. 服务器系统自检可以关吗,1366电脑服务器开机自检肿么关闭
  5. 联想服务器开机显示英文,在开机自检时,在联想LOGO画面处死机(即自检时死机)...
  6. 深度学习之 梯度消失与爆炸原因公式推导
  7. 2022 基于SpringBoot的API文档管理系统 接口文档管理系统
  8. 好用的免费CMS网站模板源码下载推荐
  9. 如何查询台式计算机的网络密码,如何查看电脑无线网络密码?两种查看方法
  10. Spring Validation 验证框架全面总结