阿狸的打字机

题解

题目中给出的字符串就是构建TrieTrieTrie树的顺序.我们将字符串依次读入,每读入一个小写字符就相当于在TrieTrieTrie树当前节点下插入一个小写字符,读入BBB时,就在TrieTrieTrie树中向父节点移动一步.读入PPP的时候,就做一个标记.

然后对这颗TrieTrieTrie树构建ACACAC自动机.

找找规律发现第xxx串在第yyy串中出现的次数就是TrieTrieTrie树上xxx串尾点到yyy串末尾点的树链上,所有能直接或间接通过failfailfail指针跳到xxx串末尾点的点的个数.

观察到自动机上failfailfail指针构成了一颗failfailfail树.

进一步我们发现,所有能直接或间接跳到xxx串末尾点的点就是failfailfail树上,xxx节点的子树大小.

而实际的答案就是failfailfail树上xxx串末尾点的子树与TrieTrieTrie树上xxx到yyy的树链的交集中点的个数.

我们对failfailfail树做一遍dfsdfsdfs序,用这个dfsdfsdfs序就可以查询和维护failfailfail树的子树的信息了.

对这个dfsdfsdfs序列建立一个树状数组.

然后我们对TrieTrieTrie树做一遍dfsdfsdfs,在dfsdfsdfs的过程中,把当前点在树状数组中的dfndfndfn位置+1+1+1,返回的时候在该位置−1-1−1,这样相当于在TrieTrieTrie树中从当前点到根节点的树链上所有节点都已经在树状数组中激活了,对于当前点作为yyy的询问,在failfailfail树的以xxx为根的子树中计算有多少个点被激活就ok了(树状数组查询前缀和).

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define LETTER 26
typedef std::pair<int,int> pii;
const int N = 100010;
char s[N];
struct Trie{int num,fail,fa;int next[LETTER];
}pool[N];
Trie* const trie = pool + 1;
int cnt;
void init() {cnt = 0;memset(pool,0,2*sizeof(Trie));trie[0].fail = -1;
}
int now;
int pat[N];
int pc;
std::vector<int> trie_edge[N];
void build() {pc = now = 0;for(int i = 0;s[i];++i) {if(s[i] == 'B') now = trie[now].fa;else if(s[i] == 'P') pat[++pc] = now;else {int &pos = trie[now].next[s[i]-'a'];if(!pos) {pos = ++cnt;memset(&trie[pos],0,sizeof(Trie));trie[pos].fa = now;trie_edge[now].push_back(pos);}now = pos;}}std::queue<int> Q;Q.push(0);while(!Q.empty()) {int t = Q.front();Q.pop();for(int i = 0;i < LETTER;++i) {int &cur = trie[t].next[i];if(cur) {Q.push(cur);trie[cur].fail = trie[trie[t].fail].next[i];}else cur = trie[trie[t].fail].next[i];}}
}
int bitree[N<<1];
int lowbit(int x) {return x & (-x);}
int sum(int pos) {int res = 0;for(;pos;pos -= lowbit(pos)) res += bitree[pos];return res;
}
void add(int pos,int x) {for(;pos < N<<1;pos += lowbit(pos))bitree[pos] += x;
}std::vector<int> edge[N];
int beg[N],end[N];
int idx = 0;
void dfs1(int u){beg[u] = ++idx;for(int v : edge[u]) dfs1(v);end[u] = ++idx;
}
std::vector<pii> query[N];
int ans[N];
void dfs2(int u) {add(beg[u],1);for(pii p : query[u]) {int x = p.first,id = p.second;ans[id] = sum(end[x])-sum(beg[x]-1);}for(int v : trie_edge[u])dfs2(v);add(beg[u],-1);
}int main() {init();std::ios::sync_with_stdio(false);std::cin >> s;build();for(int i = 1;i <= cnt;++i) edge[trie[i].fail].push_back(i);dfs1(0);int m;std::cin >> m;for(int i = 1;i <= m;++i) {int x,y;std::cin >> x >> y;query[pat[y]].push_back((pii){pat[x],i});}dfs2(0);for(int i = 1;i <= m;++i) {std::cout << ans[i] << std::endl;}return 0;
}

P2414 NOI2011阿狸的打字机 [AC自动机,dfs序]相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. CF-547E(Mike and Friends)后缀数组+线段树 AC自动机+DFS序+树状数组

    题目链接 题意 NNN个串,每次询问区间[L,R][L,R][L,R]中有多少子串SiS_iSi​ 思路 把NNN个串合成一个长字符串,对这个长字符串求后缀数组,包含SiS_iSi​的子串的heigh ...

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

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

最新文章

  1. “一切都是消息”--iMSF(即时消息服务框架)之【请求-响应】模式(点对点)...
  2. MoeCTF 2021Re部分------大佬请喝咖啡,A_game
  3. day01语法python入门_2
  4. Hibernate占位符?和:及JPA
  5. jms.jar 2.0_JMS API 1.1生产者和使用者
  6. python---python3 获取当前路径及os.path.dirname的使用;os.path.abspath(__file__)用法及意义
  7. 2.TCP/IP 详解卷1 --- 链路层
  8. Delphi Note
  9. 模拟集成电路设计初学系列
  10. ev3pid巡线_据说这是最简单的乐高EV3巡线方法
  11. 惊艳!用 Python 送女神们别样的礼物!
  12. 航空公司客户价值分析的实验报告
  13. 树莓派获取root权限
  14. Linux下文件、文件夹大小排序及文件内容排序
  15. 我的2016——程序员年到三十,工作第四年
  16. webp格式如何转成png?
  17. SpringBoot配置与应用 SpringBoot与(Spring和springmvc的区别)
  18. 北京精雕自定义机床模型仿真
  19. 阿米洛键盘取消win_阿米洛(Varmilo)
  20. 纠错技术之FEC(向前纠错)

热门文章

  1. jax rs mysql_Jersey / JAX-RS ExceptionMapper MySQL
  2. c语言铁路托运行李费用图,3.为铁路部门编写计算运费的程序。假设铁路托运行李,规定每张客票托运费计算方法是:行李重量不超过50kg...
  3. suse linux 文件只可读,SUSE LINUX下文件系统变只读的问题解决
  4. java 3des 32位密钥_3des,java_java 中32位秘钥长度的 3des加密方法?,3des,java - phpStudy...
  5. [Spring5]AOP底层原理
  6. [EDA] 2.2 简单PLD结构原理-潘松版
  7. [JavaWeb-JavaScript]JavaScript与html结合方式
  8. C++ setprecision()用法
  9. er图转为数据流程图_「数据架构」实体关系模型介绍
  10. 单片机课程设计数字心率计_如何选购合适的PH计