Description

阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和’B’、’P’两个字母。
经阿狸研究发现,这个打字机是这样工作的:
- 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
- 按一下印有’B’的按键,打字机凹槽中最后一个字母会消失。
- 按一下印有’P’的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

a
aa
ab

我们把纸上打印出来的字符串从111开始顺序编号,一直到n" role="presentation">nnn。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(x,y)(x,y)(其中1≤x,y≤n1≤x,y≤n1≤x,y≤n),打字机会显示第xxx个打印的字符串在第y" role="presentation">yyy个打印的字符串中出现了多少次。
阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?


Solution

首先对于题中所给的三个操作,对应在Trie上分别是:
- 小写字母 -> 走到当前节点的该字母的子节点(如果没有就新建一个)。
- P -> 打一个结束标记
- B -> 返回父节点
我们先根据上面的规则建出题目所给串对应的AC自动机。

AC自动机的fail树的性质:
如果自动机中的两个串ppp,s" role="presentation">sss满足ppp在s" role="presentation">sss中出现了kkk次,那么k" role="presentation">kkk等于ppp串结束点在Fail树上的子树中有多少个节点属于串s" role="presentation">sss。

有了这个性质,我们可以先求出Fail树的dfn
对于每次询问,按yyy排序,在输入的串上面走一遍,每走到一个点就将其dfn插入树状数组,每离开一个点就将其dfn在树状数组上删掉。如果走到了询问的y" role="presentation">yyy,我们查询树状数组中有多少个点再yy<script type="math/tex" id="MathJax-Element-1289">y</script>对应节点的子树的dfn范围内即可。


Code

/************************************************* Au: Hany01* Date: May 5th, 2018* Prob: [BZOJ2434][NOI2011] 阿狸的打字机* Email: hany01@foxmail.com
************************************************/#include<bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int, int> PII;
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define Mod (1000000007)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaiatemplate <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }inline int read()
{register int _, __; register char c_;for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);return _ * __;
}Statement
const int maxn = 100005;int n, Ans[maxn], dfn[maxn], efn[maxn], tot, cnt, now, len, beg[maxn], nex[maxn], v[maxn], e, clk, pos[maxn];
char s[maxn];//Aho-Corasick Automaton/struct Node
{int ch[26], fa, fail;
}t[maxn];inline void buildTrie()
{static int u = 0;rep(i, len)if (s[i] == 'B') u = t[u].fa;else if (s[i] != 'P') {register int c = s[i] - 97;if (!t[u].ch[c]) t[u].ch[c] = ++ tot, t[tot].fa = u;u = t[u].ch[c];} else pos[++ cnt] = u;cnt = 0;
}inline void getFail()
{static queue<int> q;rep(i, 26) if (t[0].ch[i]) q.push(t[0].ch[i]);while (!q.empty()) {register int u = q.front(), v, w; q.pop();rep(i, 26) if (v = t[u].ch[i]) {w = t[u].fail;while (w && !t[w].ch[i]) w = t[w].fail;t[v].fail = t[w].ch[i], q.push(v);}}
}/Build Tree//inline void add(int uu, int vv) { v[++ e] = vv, nex[e] = beg[uu], beg[uu] = e; }void getdfn(int u)
{dfn[u] = ++ clk;for (register int i = beg[u]; i; i = nex[i]) getdfn(v[i]);efn[u] = clk;
}Answer Questions/struct Question
{int p, s, id;bool operator < (const Question& A) const { return s < A.s; };
}Q[maxn];struct FenwickTree
{int c[maxn];#define lb(x) ((x) & -(x))inline void update(int x, int dt) {for ( ; x <= clk; x += lb(x)) c[x] += dt;}inline int query(int x) {register int Ans = 0;for ( ; x; x -= lb(x)) Ans += c[x];return Ans;}inline int query(int l, int r) { return query(r) - query(l - 1); }}FT;inline void Solve()
{static int u = 0;rep(i, len) {if (s[i] == 'B') FT.update(dfn[u], -1), u = t[u].fa;else if (s[i] == 'P') {++ cnt;while (cnt == Q[now].s)Ans[Q[now].id] = FT.query(dfn[pos[Q[now].p]], efn[pos[Q[now].p]]), ++ now;} else u = t[u].ch[s[i] - 97], FT.update(dfn[u], 1);}
}//Main Function//int main()
{
#ifdef hany01File("bzoj2434");
#endifscanf("%s", s), len = strlen(s);buildTrie(), getFail();For(i, 1, tot) add(t[i].fail, i);getdfn(0);n = read();For(i, 1, n) Q[i].p = read(), Q[i].s = read(), Q[i].id = i;sort(Q + 1, Q + 1 + n);now = 1, Solve();For(i, 1, n) printf("%d\n", Ans[i]);return 0;
}
//岭上逢久别者又别
//唐代 权德舆
//十年曾一别,征路此相逢。
//马首向何处?夕阳千万峰。 

【BZOJ2434】【NOI2011】阿狸的打字机(AC自动机及Fail树的性质,树状数组)相关推荐

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

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

  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】[Noi2011]阿狸的打字机 AC自动机+Dfs序+树状数组

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

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

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

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

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

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

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

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

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

  8. [luogu2414 NOI2011]阿狸的打字机 (AC自动机)

    传送门 Solution 我们知道AC自动机上如果有一点A的fail[A]->B那么B为A的一个后缀 那么我们的问题\((x,y)\)就变为在y中有多少个点直接或间接连向x的终止节点 如果写暴力 ...

  9. BZOJ2434 [Noi2011]阿狸的打字机

    AC自动机+树状数组 先建出fail树,对于查询x在y中出现几次,就等于在x为根的子树下有多少个节点为单词y在tire树路径上所在的节点,可用dfs+树状数组离线求出答案. #include<c ...

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

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

最新文章

  1. 第十二章 支持向量机-机器学习老师板书-斯坦福吴恩达教授
  2. opencv用haartraining训练出现的一些问题
  3. 使用spinner 做下拉对话框
  4. 画活动图教程_二次元人物头发怎么画?画好头发有什么技巧?
  5. mpvue 调起子组件的方法_什么是锦鲤PH值,PH调整方法有哪些?
  6. oracle修改asm参数文件,学习笔记:Oracle RAC参数文件管理 修改创建asm中的spfile文件...
  7. 计算机最早的运算领域,2013年计算机一级MsOffice模拟试题及答案38
  8. linux查看缓存的文件,linux – 如何查看缓冲和缓存的数据
  9. 移动端切图内容包括什么_ios移动端切图及前端规范
  10. 【转载】TableLayout表格布局详解
  11. JavaSE基础——方法参数类型及返回值类型问题、权限修饰符、内部类、匿名内部类
  12. Lady Gaga Feat. Colby O'Donis - Just Dance
  13. 六子冲棋,六子炮棋,二打一棋,箭棋,炮棋(java单机版)java人机对战
  14. 【NOIP2016提高组复赛】蚯蚓 题解
  15. 将多个Excel工作簿合并到一个Excel工作簿中
  16. Android 修改手机状态栏文字颜色
  17. yocs_velocity_smoother速度平滑配置与使用
  18. 【考研数学】六. 三重积分
  19. SEGGER J-FLASH V7.82 下载链接
  20. js控制浏览器窗口弹出、警告框、确认框

热门文章

  1. 线代9讲 第八讲 相似理论
  2. Windows“未安装任何音频输出设备“,扬声器红叉不可用
  3. 字体设计符号组合多功能微信小程序源码
  4. 大数据的典型应用场景及展望-札记
  5. 【使用Mac制作手写签名的方法】
  6. 嵌入式开发如何入门?
  7. 安装office后安装visiso后提示缺失文件的解决办法
  8. python如何绘制曲线图_Python matplotlib 如何绘制双Y轴曲线图?
  9. 网页数据提取----网络投票软件开发(续1)
  10. 开源分布式数据库中间件 DBLE