• 题意:一开始是个空串s,有三种操作:(1.末尾加一个字符 2.末尾减一个字符 3.存储该字符串)
  • 思路:

    一开始在trie树上动态加点很好处理,3操作的时候记录一下此时trie树上的pos,同时记录dep,fa后面有用。

    建AC自动机,因为这道题的大致思路还是:y包含于x,则x的所有前缀(trie树上的祖先节点)对应的后缀中存在y的个数和。

    因此只要y的祖先节点在fail树上对应++。然后再算x的子树和。(这里映射到dfs序上,显然树状数组维护,我一开始tm写了线段树)

    询问先按y排序,这样就可以O(|S|)跳串,具体我是ylst和y往LCA(ylst,y)上跳。过程中ylst删除贡献,y加入贡献。

    我加快读,O2跑到了第一页:

  • code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
char s[N];
int sz,n,m,pos[N],ans[N];
struct query {int x,y,id;}Q[N];
bool cmp(query u,query v) {return u.y<v.y;}
static char buf[1000000],*p1=buf,*p2=buf,obuf[1000000],*p3=obuf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
#define putchar(x) (p3-obuf<1000000)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
template<typename item>
inline void read(register item &x)
{
x=0;register char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
}
struct AC {
int c[N],fa[N],fail[N],go[N][27],nw,nd,Q[N],hd,tl,nxt[N],to[N],head[N],ecnt,In[N],Out[N],dep[N],Time,y0,rt;
void Update(int x,int d) {for(;x<=Time;x+=x&(-x))c[x]+=d;}
int Sum(int x) {int res=0;for(;x;x-=x&(-x))res+=c[x];return res;}
AC() {nw=nd=tl=Time=y0=0;hd=1;}
void add_edge(int u,int v) {nxt[++ecnt]=head[u];to[ecnt]=v;head[u]=ecnt;}
void Add(int x) {if(!go[nw][x]){go[nw][x]=++nd;fa[nd]=nw;dep[nd]=dep[nw]+1;}nw=go[nw][x];}
void Del() {nw=fa[nw];}
void Get(int &p) {p=nw;}
void init(int u) {
In[u]=++Time;
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];init(v);
}
Out[u]=Time;
}
void gt_fail() {
for(int j=0;j<26;j++)if(go[0][j])Q[++tl]=go[0][j];
while(hd<=tl) {
int u=Q[hd++];
for(int j=0;j<26;j++) {
int v=go[u][j];
if(v) fail[v]=go[fail[u]][j],Q[++tl]=v;
else go[u][j]=go[fail[u]][j];
}
}
for(int i=1;i<=nd;i++) add_edge(fail[i],i);
// for(int i=1;i<=nd;i++) printf("+ %d %d\n",fail[i],i);
init(0);
}
void solve(int id,int x,int y) {
int lst=y;
while(y!=y0) {
if(dep[y]>dep[y0]) {Update(In[y],1);y=fa[y];}
else {Update(In[y0],-1);y0=fa[y0];}
//y0 used to add lca(y,y0)
}
ans[id]=Sum(Out[x])-Sum(In[x]-1);
y0=lst;
}
}A;
int main() {
// freopen("dd.in","r",stdin);
char c;
while((c=getchar())!='\n') {
if(c=='P') {++n;A.Get(pos[n]);}
else if(c=='B') A.Del();
else A.Add(c-'a');
}
A.gt_fail();
read(m);
for(int i=1;i<=m;i++) read(Q[i].x),read(Q[i].y),Q[i].id=i;
sort(Q+1,Q+1+m,cmp);
for(int i=1;i<=m;i++) {A.solve(Q[i].id,pos[Q[i].x],pos[Q[i].y]);}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}

[NOI2011]阿狸打字机的更多相关文章

  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. [NOI2011]阿狸的打字机(好题!!!!)

    2785: [NOI2011]阿狸的打字机 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 7  Solved: 3[Submit][Status][We ...

  4. P2414 [NOI2011]阿狸的打字机

    P2414 [NOI2011]阿狸的打字机 AC自动机+树状数组 优质题解 <------题目分析 先AC自动机搞出Trie图 然后根据fail指针建一只新树 把树映射(拍扁)到一个序列上,用树 ...

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

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

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

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

  7. BZOJ2434 [Noi2011]阿狸的打字机 【AC自动机 + fail树 + 树状数组】

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3610  Solved: 1960 [Submit][S ...

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

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

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

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

随机推荐

  1. Mpvue 小程序转 Web 实践总结

    介绍 Mpvue 是一个使用 Vue.js 开发小程序的前端框架.框架基于 Vue.js 核心,修改了 Vue.js 的 runtime 和 compiler 实现,使其可以运行在小程序环境中,从而为 ...

  2. 如何使用Flannel搭建跨主机互联的容器网络

    当您将多台服务器节点组成一个Docker集群时,需要对集群网络进行设置,否则默认情况下,无法跨主机容器互联,接下来我们首先分析一下原因. 跨主机容器互联 下图描述了一个简单的集群网络,在该集群内,有两 ...

  3. java中当static块和构造函数同时出现,顺序是?

    静态块先于构造函数执行 class Student {    int age;    String name;    static int count;    public Student() {   ...

  4. Android设置TextView为不可见

    通常控件的可见与不可见分为三种情况. 第一种    gone         表示不可见并且不占用空间 第二种    visible       表示可见 第三种    invisible    表示 ...

  5. Exchange批量删除邮件

    在实际工作中经常遇到以下问题:邮件发送给错误的收件人,简而言之就是邮件发错了,如果遇到群发更麻烦.Exchange中提供了批量删除邮件功能,当用户发现发送错误后,管理员可以检索并删除指定的邮件. 案例 ...

  6. redis从0-1学习记录(完结)

    1. NoSQL(not only sql):不仅仅是数据库,非关系型数据库,关系型数据库是以表格的行列进行存储的,而非关系型数据库是以键值对进行存储,不需要固定的格式.非关系型数据库的特点,方便扩展 ...

  7. js知识梳理4.继承的模式探究

    写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...

  8. Spring配置文件-Bean生命周期配置(init-method方法,destory-method方法)

    1.UserDaoImpl类 public class UserDaoImpl implements UserDao { public UserDaoImpl(){ System.out.printl ...

  9. String类为什么被设计成不可变类

    1.享元模式: 1.共享元素模式,也就是说:一个系统中如果有多处用到了相同的一个元素,那么我们应该只存储一份此元素,而让所有地方都引用这一个元素. 2.Java中String就是根据享元模式设计的,而 ...

  10. Java学习day30

    线程分为用户线程和守护线程,虚拟机必须确保用户线程执行完毕,虚拟机不用等待守护线程执完毕 并发:同一个对象被多个线程同时操作,例如上万了同时抢100张票,手机银行和柜台同时取同一张卡里的钱 处理多线程 ...