题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2434

题解:

我写的是离线做法,不知道有没有在线做法。

转化一波题意,\(x\)在AC自动机上代表的字符串在\(y\)代表的字符串中出现的次数等于\(x\)在fail树的子树内有多少个点是\(y\)点Trie树上的祖先。

然后不难得到做法: 将询问离线按照\(y\)在AC自动机上的id排序(一个正常的构建Trie的方式建出来应该就满足节点的编号是它的Trie树DFS序).

在Trie树上DFS, 同时回答询问, 用树状数组维护即可

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std; const int N = 1e5;
const int S = 26;
struct Edge
{
int v,nxt;
} e[(N<<1)+3];
struct Query
{
int x,y,id;
bool operator <(const Query &arg) const
{
return y<arg.y;
}
} qr[N+3];
int fe[N+3];
int dfn[N+3];
int fa[N+3];
int son[N+3][S+3];
int fail[N+3];
char str[N+3];
int stk[N+3];
int id[N+3];
int que[N+3];
int bit[N+3];
int ord[N+3];
int ans[N+3];
int sz[N+3];
int n,q,siz,m,cnt,en; void addval(int lrb,int val)
{
while(lrb<=cnt)
{
bit[lrb] += val;
lrb += (lrb&(-lrb));
}
} int querysum(int rb)
{
int ret = 0;
while(rb)
{
ret += bit[rb];
rb -= (rb&(-rb));
}
return ret;
} void addedge(int u,int v)
{
en++; e[en].v = v;
e[en].nxt = fe[u]; fe[u] = en;
} void buildTrie()
{
int u = 0,tp = 0; stk[tp] = 0;
for(int i=1; i<=n; i++)
{
if(str[i]=='B')
{
stk[tp] = 0; tp--;
u = stk[tp];
}
else if(str[i]=='P')
{
m++; id[m] = u;
}
else
{
str[i]-=96;
if(!son[u][str[i]]) {siz++; son[u][str[i]] = siz;}
u = son[u][str[i]];
tp++; stk[tp] = u;
}
}
} void buildACA()
{
int head = 1,tail = 0;
for(int i=1; i<=S; i++) {if(son[0][i]) {tail++; que[tail] = son[0][i];} fail[son[0][i]] = 0;}
while(head<=tail)
{
int u = que[head]; head++;
addedge(fail[u],u); addedge(u,fail[u]);
for(int i=1; i<=S; i++)
{
if(son[u][i]) {fail[son[u][i]] = son[fail[u]][i]; tail++; que[tail] = son[u][i];}
else {son[u][i] = son[fail[u]][i];}
}
}
} void dfs(int u)
{
cnt++; dfn[u] = cnt;
sz[u] = 1;
for(int i=fe[u]; i; i=e[i].nxt)
{
if(e[i].v==fa[u]) continue;
fa[e[i].v] = u;
dfs(e[i].v);
sz[u] += sz[e[i].v];
}
} int main()
{
scanf("%s",str+1); n = strlen(str+1);
scanf("%d",&q);
buildTrie();
buildACA();
for(int i=1; i<=q; i++)
{
int x,y; scanf("%d%d",&x,&y);
qr[i].x = id[x]; qr[i].y = id[y]; qr[i].id = i;
}
dfs(0);
sort(qr+1,qr+q+1);
int u = 0,tp = 0,j = 0; stk[tp] = 0; addval(dfn[u],0);
for(int i=1; i<=n; i++)
{
if(str[i]=='B')
{
addval(dfn[u],-1);
stk[tp] = 0; tp--;
u = stk[tp];
}
else if(str[i]=='P')
{
while(j<q && qr[j+1].y==u)
{
j++;
ans[qr[j].id] = querysum(dfn[qr[j].x]+sz[qr[j].x]-1)-querysum(dfn[qr[j].x]-1);
}
}
else
{
u = son[u][str[i]];
tp++; stk[tp] = u;
addval(dfn[u],1);
}
}
for(int i=1; i<=q; i++)
{
printf("%d\n",ans[i]);
}
return 0;
}

BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)的更多相关文章

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

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

  2. [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组

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

  3. BZOJ2434: [Noi2011]阿狸的打字机(AC自动机 树状数组)

    Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4140  Solved: 2276[Submit][Status][Discuss] Descript ...

  4. [BZOJ2434][Noi2011]阿狸的打字机 AC自动机+树状数组+离线

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题目中这种多个串匹配的问题,一下子就想到了AC自动机.然后发现如果要建立AC自动机, ...

  5. BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)

    题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...

  6. bzoj 2434 阿狸的打字机 - Aho-Corasick自动机 - 树状数组

    题目传送门 传送站I 传送站II 题目大意 阿狸有一个打字机,它有3种键: 向缓冲区追加小写字母 P:打印当前缓冲区(缓冲区不变) B:删除缓冲区中最后一个字符 然后多次询问第$x$个被打印出来的串在 ...

  7. P2414 [NOI2011]阿狸的打字机 AC自动机

    题意 给定n个模式串,有m个询问,每次询问第X个模式串在第Y个模中出现了多少次 解题思路 以fail树相反的方向建一棵树T,问题转化为X的子树中有多少个y的终止节点.跑出T的dfs序,X的子树就可以表 ...

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

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

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

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

随机推荐

  1. YTU 2782: 用数字造数字

    2782: 用数字造数字 时间限制: 1 Sec  内存限制: 128 MB 提交: 191  解决: 160 题目描述 输入一个3位以上的整数,求其中最大的数字最小的数字之间的差.例如:输入8729 ...

  2. JSP-Runoob:JSP 页面重定向

    ylbtech-JSP-Runoob:JSP 页面重定向 1.返回顶部 1. JSP 页面重定向 当需要将文档移动到一个新的位置时,就需要使用JSP重定向了. 最简单的重定向方式就是使用respons ...

  3. 如何在vue项目中引入阿里巴巴的iconfont图库

    1. 打开 http://www.iconfont.cn/ 2. 选择我们喜欢的图标,点击上面的小车,加入图标库,即右侧的购物车 3.点击购物车,点击下载代码 4.解压下载的文件夹,将文件夹复制到 a ...

  4. php排序函数测试

    1.sort,asort,arsort函数 十万个数的数组排序,用了0.17秒 $starttime=explode(' ',microtime());;for ($i=0; $i <10000 ...

  5. [Swift通天遁地]九、拔剑吧-(14)创建更美观的景深视差滚动效果

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  6. idea ssm项目移包报错问题

    写完代码之后发现包结构太乱了  想要规划一下  结果报错 这里面的包路径都可以点进去,还是报找不到com.lf.company.entity.Business 后来发现是 在移动前和移动后都存在这个m ...

  7. DFS之城堡问题

    2019-06-01 17:54:51 坚持!! 题目链接: http://bailian.openjudge.cn/practice/2815 #include <bits/stdc++.h& ...

  8. $Vijos P1250$

    背包? 跑完并查集 分组背包完事 #include <bits/stdc++.h> #define rep(i,j,n) for(register int i=j;i<=n;i++) ...

  9. 深入理解async和await的作用及各种适用场景和用法

    https://www.cnblogs.com/yaopengfei/archive/2018/07/02/9249390.html https://www.cnblogs.com/xianyudot ...

  10. 执行update, insert,delete 语句, 不返回结果集,(类型化参数)

    /// <summary> /// 执行update, insert,delete 语句, 不返回结果集,(类型化参数) /// </summary> /// <para ...