Description

题库链接

给你 \(n\) 个单词, \(m\) 组询问,每组询问形同 \((x,y)\) ,询问 \(x\) 串在 \(y\) 串中出现多少次。

\(1\leq n,m\leq10^5\)

Solution

比较暴力的做法就是建好 \(AC\) 自动机后,对于每个 \(y\) 串暴力跑一遍。看看查询的时候有多少次落在了 \(x\) 串的末尾。

我们可以构建 \(fail\) 树,那么其实题目可以转变为对于 \(x\) 串末尾节点,其子树中有多少个节点位于 \(y\) 串上。

由于题目的特殊性,我们可以离线询问按照 \(y\) 来排序。并且预处理出 \(AC\) 自动机的 \(dfn\) 。

我们按照构建 \(Trie\) 树的操作再按原字符串走一遍。入栈时对应的 \(dfn\) 处 \(+1\) ,出时对应的 \(dfn\) 处 \(-1\) 。那么走到一个单词节点,所有打上标记的 \(dfn\) 都是该单词上的。

注意到一个子树内的 \(dfn\) 都是连续的,显然就可以回答所有 \(y\) 等于该单词的询问了。树状数组维护 \(dfn\) 的标记的前缀和即可。

Code

//It is made by Awson on 2018.3.18
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 100000;
void read(int &x) {char ch; bool flag = 0;for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }char ch[N+5];
int n, m, idx, dfn[N+5], size[N+5], ans[N+5], mp[N+5];
struct tt {int to, next; }edge[(N<<1)+5];
struct qu {int x, y, id;bool operator < (const qu &b) const {return y < b.y; }
}que[N+5];
int path[N+5], top;
void add(int u, int v) {edge[++top].to = v, edge[top].next = path[u], path[u] = top; }
struct bittree {int c[N+5];void add(int o, int val) {for (; o <= idx; o += lowbit(o)) c[o] += val; }int count(int o) {int ans = 0; for (; o; o -= lowbit(o)) ans += c[o]; return ans; }
}BT;
struct Trie {int ch[N+5][26], pre[N+5], f[N+5], val[N+5], pos;void build(char *S) {int u = 0;for (int i = 0, len = strlen(S); i < len; i++) {if (S[i] == 'P') {val[u] = ++n, mp[n] = u; continue; }if (S[i] == 'B') {u = pre[u]; continue; }if (ch[u][S[i]-'a'] == 0) ++pos, pre[pos] = u, ch[u][S[i]-'a'] = pos;u = ch[u][S[i]-'a'];}}void get_fail() {queue<int>Q;for (int i = 0; i < 26; i++) if (ch[0][i]) f[ch[0][i]] = 0, Q.push(ch[0][i]);while (!Q.empty()) {int u = Q.front(); Q.pop();for (int i = 0; i < 26; i++) {if (ch[u][i]) f[ch[u][i]] = ch[f[u]][i], Q.push(ch[u][i]);else ch[u][i] = ch[f[u]][i];}}for (int i = 1; i <= pos; i++) add(f[i], i);}void query(char *S) {int loc = 1, u = 0;for (int i = 0, len = strlen(S); i < len; i++) {if (S[i] == 'P') {while (loc <= m && que[loc].y == val[u])ans[que[loc].id] = BT.count(dfn[mp[que[loc].x]]+size[mp[que[loc].x]]-1)-BT.count(dfn[mp[que[loc].x]]-1), ++loc;}else if (S[i] == 'B') BT.add(dfn[u], -1), u = pre[u];else u = ch[u][S[i]-'a'], BT.add(dfn[u], 1);}}
}T;
void dfs(int o) {size[o] = 1, dfn[o] = ++idx;for (int i = path[o]; i; i = edge[i].next) {dfs(edge[i].to); size[o] += size[edge[i].to];}
}void work() {scanf("%s", ch); T.build(ch); T.get_fail();dfs(0); read(m);for (int i = 1; i <= m; i++) read(que[i].x), read(que[i].y), que[i].id = i;sort(que+1, que+1+m); T.query(ch);for (int i = 1; i <= m; i++) writeln(ans[i]);
}
int main() {work(); return 0;
}

转载于:https://www.cnblogs.com/NaVi-Awson/p/8597314.html

[NOI 2011]阿狸的打字机相关推荐

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

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

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

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

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

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

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

    2434: [Noi2011]阿狸的打字机 https://lydsy.com/JudgeOnline/problem.php?id=2434 分析: AC自动机. 查询x在y中出现了几次,就是查询y ...

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

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

  6. 【bzoj 2434】【codevs 1946】[Noi2011]阿狸的打字机(AC自动机)

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

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

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

  8. [NOI2011] 阿狸的打字机

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

  9. 【NOI 2011】阿狸的打字机

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

最新文章

  1. tornado源码分析
  2. Linux模块机制浅析
  3. QT实现Media Player(媒体播放器)
  4. sawmill全方位日志分析大师
  5. python,时间加减,时间计算,时间格式化,时间提取汇总
  6. 做骨龄检测_小柚熊:骨龄测试最佳年龄
  7. 分布式消息流平台:不要只想着Kafka,还有Pulsar
  8. PFC_颗粒流软件_喷射混凝土模拟
  9. c语言解线性方程组矩阵形势,c语言解线性方程组.docx
  10. 生活中的逻辑谬误01.诉诸纯洁
  11. jy在线制图系统免费源码丨一秒生成广告横图海报图
  12. 挥别2022再战2023 | 平行云“逆势增长”与“顺势而为”
  13. 国内VR体验馆发展现状及未来前景
  14. 实例10:四足机器人运动学逆解可视化与实践
  15. CentOS安装netstat,ifconfig命令
  16. 基于OSM的地图大数据应用开发-1
  17. 怎样将文档生成链接或二维码
  18. 免费申请office365 A1 和 a1p 带OneDrive 5T 网盘 office365学生版
  19. FZU 2238 Daxia Wzc's problem【规律+lucas】
  20. 市场疲软谁能跨越周期,复苏之后谁将胜者为王?

热门文章

  1. 微信不给下载app如何解决
  2. html语言花店界面模板,超级漂亮的网上花店html静态页面
  3. 用 Python 帮财务小妹生成 Excel 报表,小妹直说一辈子。。。
  4. (十)Core Java 面向对象(封装,继承,多态,接口) -02 (96)
  5. 如何选择优秀的期货公司开户
  6. python中声明变量注意要项_Python之变量、常量以及注释
  7. word,鼠标每点击一次,总转圈一会
  8. Java Label
  9. 5个Excel办公必备的技巧,职场小白务必牢记于心!
  10. Selenium IDE