bzoj 2434 AC自动机 + fail指针建树 + 树状数组
思路:我们先跟着它给定的字符串走把字典树建出来,求出fail指针,我们考虑两个字符串 A和B,
如果想要求B中有多少A的子串,转换一下就是有多少个B的前缀的后缀包含A,这个在AC自动机
的状态图中很容易表示,就是字符串B所占的结点中 有多少个结点顺着fail能到达A的尾结点,
并且fail构建出来的图是一棵树,转换成A的尾结点的子树中有多少个B的节点,用dfs序构建树状
数组能很容易完成,又因为有m组询问,我们把询问离线排序,就能解决问题啦。
#include<bits/stdc++.h>
#define LL long long
#define ll long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg using namespace std; const int N = 2e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = ; int n, m, pos, ans[N], t[N];
char s[N]; struct Qus {
int x, y, id;
bool operator < (const Qus &rhs) const {
return y < rhs.y;
}
} qus[N]; struct BIT {
int a[N];
void modify(int x, int v) {
for(int i = x; i < N; i += i & -i)
a[i] += v;
}
int sum(int x) {
int ans = ;
for(int i = x; i; i -= i & -i)
ans += a[i];
return ans;
}
} bit; struct Ac {
int ch[N][], val[N], dp[N], f[N], L[N], R[N], tot, sz, cnt, all;
bool vis[N];
vector<PII> vec[N];
vector<int> edge[N]; Ac(int sz) {this->sz = sz;}
void init() {tot = ;}
int newNode() {
tot++; f[tot] = ; val[tot] = ;
memset(ch[tot], , sizeof(ch[tot]));
return tot;
}
inline int idx(char c) {return c - 'a';}
void addStr(char *s) {
stack<int> stk;
int u = ;
stk.push();
for(int i = ; s[i]; i++) {
if(s[i] == 'P') {
cnt++; val[u]++; t[cnt] = u;
while(pos <= n && qus[pos].y <= cnt)
vec[u].push_back(mk(qus[pos].x, qus[pos].id)), pos++;
} else if(s[i] == 'B') {
if(stk.size() > ) {
stk.pop();
u = stk.top();
}
} else {
int c = idx(s[i]);
if(!ch[u][c]) ch[u][c] = newNode();
u = ch[u][c];
stk.push(u);
}
}
} void build() {
queue<int> que;
for(int c = ; c < sz; c++) {
int v = ch[][c];
if(!v) ch[][c] = ;
else f[v] = , que.push(v);
}
while(!que.empty()) {
int u = que.front(); que.pop();
val[u] |= val[f[u]];
for(int c = ; c < sz; c++) {
int v = ch[u][c];
if(!v) ch[u][c] = ch[f[u]][c];
else f[v] = ch[f[u]][c], que.push(v);
}
}
} void dfs(int u) {
L[u] = ++all;
for(int i = ; i < edge[u].size(); i++) {
int v = edge[u][i];
dfs(v);
}
R[u] = all;
} void solve(char *s) {
for(int i = ; i <= tot; i++)
edge[f[i]].push_back(i); dfs(); stack<int> stk;
int u = ;
stk.push();
bit.modify(L[], );
for(int i = ; s[i]; i++) {
if(s[i] == 'P') {
if(vis[u]) continue;
vis[u] = true; for(int i = ; i < vec[u].size(); i++) {
int x = t[vec[u][i].fi], id = vec[u][i].se;
ans[id] = bit.sum(R[x]) - bit.sum(L[x] - );
}
} else if(s[i] == 'B') {
if(stk.size() > ) {
bit.modify(L[u], -);
stk.pop();
u = stk.top();
}
} else {
int c = idx(s[i]);
u = ch[u][c];
stk.push(u);
bit.modify(L[u], );
}
}
for(int i = ; i <= n; i++) printf("%d\n", ans[i]);
}
} ac(); int main() {
ac.init(); pos = ;
scanf("%s%d", s, &n);
for(int i = ; i <= n; i++) {
scanf("%d%d", &qus[i].x, &qus[i].y);
qus[i].id = i;
}
sort(qus + , qus + + n);
ac.addStr(s);
ac.build();
ac.solve(s);
return ;
} /*
*/
bzoj 2434 AC自动机 + fail指针建树 + 树状数组的更多相关文章
- bzoj 2434 AC自动机+树状数组
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3493 Solved: 1909[Submit][Sta ...
- 【BZOJ】1818: [Cqoi2010]内部白点(树状数组+离散+特殊的技巧)
http://www.lydsy.com/JudgeOnline/problem.php?id=1818 这一题一开始我就看错了,bzoj的那个绝对值109简直坑人,应该是10^9,我直接写了个暴力. ...
- bzoj 1818 [CQOI 2010] 内部白点 - 扫描线 - 树状数组
题目传送门 快速的列车 慢速的列车 题目大意 一个无限大的方格图内有$n$个黑点.问有多少个位置上下左右至少有一个黑点或本来是黑点. 扫描线是显然的. 考虑一下横着的线段,取它两个端点,横坐标小的地方 ...
- BZOJ 3236 AHOI 2013 作业 莫队+树状数组
BZOJ 3236 AHOI 2013 作业 内存限制:512 MiB 时间限制:10000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目大意: 此时己是凌晨两点,刚刚做了Co ...
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2221 Solved: 1179[Submit][Sta ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树
[题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...
- 【BZOJ】1012: [JSOI2008]最大数maxnumber(树状数组+rmq)
http://www.lydsy.com/JudgeOnline/problem.php?id=1012 树状数组原来我只懂得sum和add的操作,今天才知道可以有求区间最值的操作,我学习了一下写了个 ...
- 【BZOJ 3295】动态逆序对 - 分块+树状数组
题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...
- BZOJ 1878: [SDOI2009]HH的项链 离线树状数组
1878: [SDOI2009]HH的项链 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
随机推荐
- select和epoll概念
关于linux的I/O复用接口select和epoll,下列说法错误的是() select调用时会进行线性遍历,epoll采用回调函数机制,不需要线性遍历 select的最大连接数为FD_SETSIZ ...
- java web中resources路径
UserBean.class.getClassLoader().getResource(filePath).getPath() 或者 Thread.currentThread().getContext ...
- 深度解析Java多线程的内存模型
内部java内存模型 硬件层面的内存模型 Java内存模型和硬件内存模型的联系 共享对象的可见性 资源竞速 Java内存模型很好的说明了JVM是如何在内存里工作的,JVM可以理解为java执行的一个操 ...
- UVA 1635 Irrelevant Elements
https://vjudge.net/problem/UVA-1635 题意:n个数,每相邻两个求和,最后变成1个数,问这个数除m的余数与第几个数无关 n个数使用次数分别为C(n-1,i) i∈[0, ...
- svn全备加强版
svn版本库备份 官方建议使用如下方法备份(全备) svnadmin hotcopy path/to/repository path/to/backup 链接:https://tortoisesvn. ...
- 【BZOJ】1709: [Usaco2007 Oct]Super Paintball超级弹珠
[算法]模拟 [题解]O(n^2)预处理横线(y),纵线(x),主对角线(y-x+n),副对角线(x+y). 然后n^2枚举每个点.
- 【转】IOS版本自定义字体步骤
本文转载自:http://quick.cocoachina.com/wiki/doku.php?id=ios%E7%89%88%E6%9C%AC%E4%BD%BF%E7%94%A8%E8%87%AA% ...
- luaj luaoc 回调函数传递的一些小总结
问题场景:我们的游戏在支付时,由于第三方支付比较费时,可能在支付的过程中,我们lua写的cocos2dx项目会断网,我们的游戏有自动重连的机制.我就想,如果断线好了以后,支付完成了,那在断网之前传入的 ...
- 【HNOI】矩阵染色 数论
[题目描述]一个2*i的矩阵,一共有m种颜色,相邻两个格子颜色不能相同,m种颜色不必都用上,f[i]表示这个答案,求Σf[i]*(2*i)^m (1<=i<=n)%p. [数据范围] 20 ...
- 项目记录 -- zpool set
zfs set <property=value> <filesystem|volume|snapshot> root@UA4300D-spa:~/hanhuakai/pro_0 ...