描述


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

给出\(n\)个字符串,\(m\)个询问,对于第\(i\)个询问,求第\(x_i\)个字符串在第\(y_i\)个字符串中出现了多少次.

分析


首先我们可以想到对于串\(x\)和串\(y\),如果\(x\)在\(y\)中出现过,那么\(x\)一定是(\(y\)的某个前缀)的后缀,如果我们用所有字符串建立一个AC自动机,那么对于这个前缀,沿着失配边走,一定能走到\(x\)串.

所以我们得到了一个很直观但是复杂度很高的算法:对于每一个询问,枚举\(y\)中的字符作为前缀的结尾,沿着失配边走,看是否能够走到\(x\)串,复杂度是\(O(mL^2)\).显然这种算法是要超时的,我们需要考虑更优的算法.

这里先介绍fail树这一概念.对于AC自动机上的点\(x\),我们连一条\(f[x]\to{x}\)的有向边,这样就形成了一棵fail树.

这时我们会发现,之前说的能够沿着失配边找到\(x\)串的\(y\)串的后缀,一定在\(x\)的子树当中.我们用dfs序把树上问题转化为区间问题,问题就转化为了在区间内找符合条件的点有多少个.我们把\(y\)的后缀标为\(1\),其他全部标为\(0\),然后处理所有有关\(y\)的询问,由于是区间问题,可以用树状数组维护.

这样的算法的复杂度是\(O(mlogn)\)的.

 #include <bits/stdc++.h>
using namespace std;
inline int read(int &x){x=;int k=;char c;for(c=getchar();c<''||c>'';c=getchar())if(c=='-')k=-;for(;c>=''&&c<='';c=getchar())x=x*+c-'';return x*=k;} const int maxn=1e5+,type=;
int n,qct;
int ans[maxn];
char s[maxn];
struct query{
int x[maxn],next[maxn],hd[maxn];
inline void add_query(int a,int b){
x[++qct]=a; next[qct]=hd[b]; hd[b]=qct;
}
}Q;
struct Aho_Corasick{
int sz,cnt,ect;
int q[maxn],hd[maxn],f[maxn],fa[maxn],val[maxn],pos[maxn],l[maxn],r[maxn],c[maxn<<];
int ch[maxn][type];
struct edge{
int to,next;
edge(){}
edge(int to,int next):to(to),next(next){}
}g[maxn];
Aho_Corasick(){sz=cnt=;memset(ch[],,sizeof ch[]);}
inline int id(char c){return c-'a';}
inline int lowbit(int x){return x&-x;}
inline void add_edge(int u,int v){g[++ect]=edge(v,hd[u]);hd[u]=ect;}
inline void build_trie(){
int m=strlen(s+);
int u=;
for(int i=;i<=m;i++){
int c=id(s[i]);
if(c=='P'-'a'){val[u]=++cnt,pos[cnt]=u;continue;}
if(c=='B'-'a'){u=fa[u];continue;}
if(!ch[u][c]){
memset(ch[++sz],,sizeof ch[sz]);
ch[u][c]=sz;
fa[sz]=u;
}
u=ch[u][c];
}
}
inline void get_fail(){
int L=,R=;
for(int c=;c<type;c++){
int u=ch[][c];
if(u){f[u]=;add_edge(,u);q[++R]=u;}
}
while(L<=R){
int u=q[L++];
for(int c=;c<type;c++){
int t=ch[u][c];
if(!t){ch[u][c]=ch[f[u]][c];continue;}
int v=f[u];
f[t]=ch[v][c];
add_edge(f[t],t);
q[++R]=t;
}
}
}
void dfs(int x,int &t){
l[x]=++t;
for(int i=hd[x];i;i=g[i].next) dfs(g[i].to,t);
r[x]=++t;
}
inline void add(int x,int d){
int R=sz<<;
while(x<=R){
c[x]+=d;
x+=lowbit(x);
}
}
inline int sum(int x){
int ret=;
while(x>){
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
inline void solve(){
int m=strlen(s+);
int u=;
for(int i=;i<=m;i++){
int c=id(s[i]);
if(c=='B'-'a'){add(l[u],-);u=fa[u];continue;}
if(c=='P'-'a'){
int y=val[u];
for(int j=Q.hd[y];j;j=Q.next[j]){
int x=Q.x[j];
ans[j]=sum(r[pos[x]])-sum(l[pos[x]]-);
}
continue;
}
u=ch[u][c];
add(l[u],);
}
}
}ac;
inline void init(){
scanf("%s",s+);
ac.build_trie();
read(n);
for(int i=,a,b;i<=n;i++){
read(a); read(b);
Q.add_query(a,b);
}
}
inline void solve(){
ac.get_fail();
int t=;
ac.dfs(,t);
ac.solve();
for(int i=;i<=n;i++) printf("%d\n",ans[i]);
}
int main(){
init();
solve();
return ;
}

2434: [Noi2011]阿狸的打字机

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 2296  Solved: 1298
[Submit][Status][Discuss]

Description

阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。

经阿狸研究发现,这个打字机是这样工作的:

l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。

l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。

例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

a

aa

ab

我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

Input

输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。

第二行包含一个整数m,表示询问个数。

接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。

Output

输出m行,其中第i行包含一个整数,表示第i个询问的答案。

Sample Input

aPaPBbP

3

1 2

1 3

2 3

Sample Output

2

1

0

HINT

1<=N<=10^5

1<=M<=10^5
输入总长<=10^5

Source

BZOJ_2434_[NOI2011]_阿狸的打字机_(AC自动机+dfs序+树状数组)的更多相关文章

  1. BZOJ2434: [NOI2011]阿狸的打字机(AC自动机+dfs序+树状数组)

    [NOI2011]阿狸的打字机 题目链接:https://www.luogu.org/problemnew/show/P2414 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. ...

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

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

  3. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

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

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

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

  5. NOI 2011 阿狸的打字机 (AC自动机+dfs序+树状数组)

    题目大意:略(太长了不好描述) 良心LOJ传送门 先对所有被打印的字符串建一颗Trie树 观察数据范围,并不能每次打印都从头到尾暴力建树,而是每遍历到一个字符就在Trie上插入这个字符,然后记录每次打 ...

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

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

  7. 【BZOJ2434】【NOI2011】阿狸的打字机(AC自动机,树状数组)

    [BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...

  8. 【AC自动机】【树状数组】【dfs序】洛谷 P2414 [NOI2011]阿狸的打字机 题解

        这一题是对AC自动机的充分理解和树dfs序的巧妙运用. 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和' ...

  9. 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

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

随机推荐

  1. poj 2947 Widget Factory

    Widget Factory 题意:有n件装饰品,有m组信息.(1 <= n ,m<= 300)每组信息有开始的星期和结束的星期(是在mod 7范围内的)并且还包括num种装饰品的种类(1 ...

  2. iOS中为网站添加图标到主屏幕以及增加启动画面

    虽然没有能力开发Native App,但还是可以利用iOS中Safari浏览器的特性小小的折腾一下,做一个伪Web App满足下小小的虚荣心的. 既然是在iOS中的Safari折腾的,那么代码中利用到 ...

  3. JavaScript与DOM的关系

    JavaScript与浏览器的工作 1.浏览器获取并加载你的页面,从上至下解析它的内容. 遇到JavaScript时,浏览器会解析代码,检查它的正确性,然后执行代码. 浏览器还会建立一个HTML页面的 ...

  4. ExtJS4.2学习(四)Grid表格中文排序问题(转)

    鸣谢:http://www.shuyangyang.com.cn/jishuliangongfang/qianduanjishu/2013-11-07/173.html --------------- ...

  5. oracle中int类型和number类型区别

    INT类型是NUMBER类型的子类型.下面简要说明:(1)NUMBER(P,S)该数据类型用于定义数字类型的数据,其中P表示数字的总位数(最大字节个数),而S则表示小数点后面的位数.假设定义SAL列为 ...

  6. glibc库详解及与POSIX,system V这些库之间关系的说明

    自己想了解下关于system v,在网上看到一篇详细的说明,与大家分享一下,原文地址http://hi.baidu.com/tekuba/item/570887775696542e5c178918 以 ...

  7. c缺陷与陷阱笔记-第一章 词法陷阱

    1.运算符的贪心性,匹配最长的运算符,例如 n-->0,从-开始,-是运算符,--是运算符,-->就不是,所以是 n -- > 0,--是 a---b,-是,--是,,---不是,所 ...

  8. MVC项目总结(别人的好文章)

    引用 http://www.cnblogs.com/xling/archive/2012/07/11/2587002.html

  9. mvc+entity framework database first,生成的model每次更新一个表会更新所有的model

    在使用Entity Framework 的Database frist或model first时,直接加attribute到modle类上是太现实也不合理的,因为model类是自动生成的,重新生成后会 ...

  10. 【BZOJ 1038】 1038: [ZJOI2008]瞭望塔

    1038: [ZJOI2008]瞭望塔 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 ...