【题目链接】

  

  http://www.lydsy.com/JudgeOnline/problem.php?id=2434

【题意】

  按照一定规则生成n个字符串,回答若干个询问:(x,y),问第x个字符串在第y个字符串中的出现次数。

【思路】

用所有的串构建AC自动机并求出fail数组,利用fail指针构建fail树,在这棵树上父亲是儿子的最大后缀。对于询问(x,y),设自动机中y对应的尾节点为pos,即统计自动机上pos-root的路径上的结点中有多少个处于fail树中的x的子树中。

一棵树的子树中的所有节点对应于dfs序上的一段连续区间,求出dfs序后,统计就可以转化为区间和问题,用到BIT。

离线处理所有的询问,统计所有关于y的询问到que[y],再用O(n)加一遍节点,我们对路上的所有节点对应+1,当访问到节点rt时,root-rt路径上的所有节点都已经访问,处理关于rt的询问即可。

总的时间复杂度为O(nlogn)。

【代码】

 #include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int N = 1e5+;
char s[N];
int C[N],ans[N],n;
vector<pair<int,int> > que[N]; void add(int x,int v) {
while(x<N) C[x]+=v,x+=x&-x;
}
int query(int x) {
int res=;
while(x) res+=C[x],x-=x&-x;
return res;
}
struct ACauto {
int sz,ch[N][],fa[N],l[N],r[N],pos[N],f[N],dfsc;
vector<int> g[N];
ACauto() { sz=;dfsc=; memset(ch,,sizeof(ch)); }
void insert() {
int u=,id=;
for(int i=;s[i];i++) {
if(s[i]=='P') pos[++id]=u;
else if(s[i]=='B') u=fa[u];
else {
int c=s[i]-'a';
if(!ch[u][c]) {
ch[u][c]=sz; fa[sz]=u; sz++;
}
u=ch[u][c];
}
}
}
void get_Fail() {
queue<int> q;
f[]=;
for(int c=,v;c<;c++)
if(ch[][c]) f[ch[][c]]=,q.push(ch[][c]);
while(!q.empty()) {
int qr=q.front(); q.pop();
for(int c=;c<;c++) {
int u=ch[qr][c];
if(!u) continue;
q.push(u); int v=f[qr];
while(v&&!ch[v][c]) v=f[v];
f[u]=ch[v][c];
}
}
for(int i=;i<sz;i++)
g[f[i]].push_back(i);
}
void get_dfsc(int u) {
l[u]=++dfsc;
for(int i=;i<g[u].size();i++)
get_dfsc(g[u][i]);
r[u]=dfsc;
}
void solve() {
int id=,u=;
add(l[],);
for(int i=;s[i];i++) {
if(s[i]=='P') {
id++;
for(int j=;j<que[id].size();j++) {
int x=pos[que[id][j].first];
ans[que[id][j].second]=query(r[x])-query(l[x]-);
}
}
else if(s[i]=='B') add(l[u],-),u=fa[u];
else u=ch[u][s[i]-'a'],add(l[u],);
}
}
}ac; void read(int& x) {
char c=getchar(); int f=; x=;
while(!isdigit(c)){if(c=='-')f=-;c=getchar();}
while(isdigit(c)) x=x*+c-'',c=getchar();
x*=f;
}
int main() {
scanf("%s",s);
ac.insert();
ac.get_Fail();
ac.get_dfsc();
read(n);
int x,y;
for(int i=;i<n;i++) {
read(x),read(y);
que[y].push_back(make_pair(x,i));
}
ac.solve();
for(int i=;i<n;i++)
printf("%d\n",ans[i]);
return ;
}

bzoj 2434 [Noi2011]阿狸的打字机(fail树+离线处理+BIT)的更多相关文章

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

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

  2. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  3. bzoj 2434 [Noi2011]阿狸的打字机 AC自动机

    [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4001  Solved: 2198[Submit][Status][D ...

  4. BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机+fail树+线段树

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

  5. 【BZOJ 2434】 [Noi2011]阿狸的打字机 fail树+树状数组

    就是考了一个fail树的神奇应用我们建出fail树之后,发现我们就是在求y到根的路径上所有的点在以x为根的子树里的个数,这个我们离线后用树状数组+dfs序即可解决 #include <cstdi ...

  6. BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题目大意] 给出一个打印的过程,'a'-'z'表示输入字母,P表示打印该字符串 ...

  7. bzoj 2434 [Noi2011]阿狸的打字机——AC自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2434 dfs AC自动机,走过的点权值+1,回溯的时候权值-1:走到询问的 y 串的节点,看 ...

  8. bzoj 2434: 阿狸的打字机 fail树+离线树状数组

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程 所以我们 ...

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

    #include<cstdio> #include<iostream> #include<cstring> #define M 100008 using names ...

随机推荐

  1. python上下文管理器及with语句

    with语句支持在一个叫上下文管理器的对象的控制下执行一系列语句,语法大概如下: with context as var: statements 其中的context必须是个上下文管理器,它实现了两个 ...

  2. C#中的==、Equal、ReferenceEqual(转载)

    1. ReferenceEquals, == , Equals Equals , == , ReferenceEquals都可以用于判断两个对象的个体是不是相等. a) ReferenceEquals ...

  3. hdu 4358 Boring counting 离散化+dfs序+莫队算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意:以1为根节点含有N(N <= 1e5)个结点的树,每个节点有一个权值(weight ...

  4. 2016041601 - maven用途

    以前只是使用maven只是当成jar依赖管理工具,并没有想到它有多么厉害的功能.现在看书系统学习maven才发现它的强大之处.个人认为通过博客去学习掌握一门技术,这是很低层次的学习方法.学习金字塔,学 ...

  5. HttpContext

    HttpContext 类:封装有关个别 HTTP 请求的所有 HTTP 特定的信息.也有人叫上下文信息. 1.生存周期:从客户端用户点击并产生了一个向服务器发送请求开始---服务器处理完请求并生成返 ...

  6. objective-c常用数学方法

    1. 三角函数  double sin (double);正弦  double cos (double);余弦  double tan (double);正切  2 .反三角函数  double as ...

  7. ios阻止锁屏 --老代码,供参考

    // Disable the idle timer [[UIApplication sharedApplication] setIdleTimerDisabled: YES];    // Or fo ...

  8. Codeforces Round #359 div2

    Problem_A(CodeForces 686A): 题意: \[ 有n个输入, +\space d_i代表冰淇淋数目增加d_i个, -\space d_i表示某个孩纸需要d_i个, 如果你现在手里 ...

  9. scrollview始终显示滚动条 Android

    设置scrollview的:android:fadeScrollbars="false"表示始终显示垂直滚动条

  10. [XJOI NOI2015模拟题13] B 最小公倍数 【找规律】

    题目链接:XJOI - NOI2015-13 - B 题目分析 通过神奇的观察+打表+猜测,有以下规律和性质: 1) 删除的 n 个数就是 1~n. 2) 当 c = 2 时,如果 n + 1 是偶数 ...