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 ...
随机推荐
- bzoj 1564 [NOI2009]二叉查找树 区间DP
[NOI2009]二叉查找树 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 906 Solved: 630[Submit][Status][Discu ...
- sgu 131 状压DP
棋盘覆盖(二) 时间限制:1000 ms | 内存限制:65535 KB 描述 The banquet hall of Computer Scientists' Palace has a ...
- javascript功能封装
实现方式其实很简单,我在代码打上注释,大家就懂了! var _date=[],dateData=["1月","2月","3月",&qu ...
- SpringBoot打war包并部署到tomcat下运行
一.修改pom.xml. 1.packaging改为war 2.build节点添加<finalName>你的项目名</finalName> 二.修改项目启动类,继承Spring ...
- idea中设置springboot热部署
在idea中设置springboot热部署,项目修改的时候不用手动重启应用 1,pom中添加依赖 <dependency> <groupId>org.springframewo ...
- [SDOI2011] 染色(Luogu 2486)
题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C ...
- 「6月雅礼集训 2017 Day7」回转寿司
[题目大意] 给一个n个数的序列,q次操作,每次选择区间$[l,r]$,给出数p,对于区间$[l,r]$的每个数$x$,做如下操作: 如果$x > p$,就交换$x$和$p$.求每次操作后$p$ ...
- Bzoj4873 [SXOI2017]寿司餐厅
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 64 Solved: 45 Description Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每 ...
- 【TYVJ】P1038 忠诚
[算法]线段树 #include<cstdio> #include<algorithm> using namespace std; ]; ,inf=0x3f3f3f3f; in ...
- Python学习笔记 - day11 - Python操作数据库
MySQL的事务 MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关,MySQL的两种引擎如下: 1.MyISAM:不支持事务,用于只读程序提高性能 2.InnoDB:支持ACID ...