如标题所言,我已经沉迷于AC自动机无法自拔了。。。
这又是一道AC自动的题,红红火火恍恍惚惚



这题目做起来真舒服
简单概括一下:\(AC\)自动机\(fail\)树上树链剖分\(+\)树状数组
这种类型的题其实还蛮多的,比如这道:[HDU 4117] GRE Words
$
$
首先把\(AC\)自动机建出来,然后在所有子节点连一条由\(fail\)指向该点的边,这样一棵\(fail\)树就出来了。
题目问的是:求\(x\)在\(y\)中出现多少次,把问题放到\(fail\)树上来,就变成了:求从根到\(y\)的的节点中(这里指的是\(dfs\)序从根到\(y\)),有多少个在\(x\)的子树内
那么这个东西就很好求了,像普通的树链剖分题那样,用线段树就能维护,但是这道题只要查\(root\)到\(y\),\(bit\)也适用且常数要更小些
具体做法:我们离线来做这道题,把\(y\)相同的询问放到一起来处理
考虑这样几个做法:

  1. 每次遇到\('P'\)则统计答案当前点\(y\)的所有询问的答案;
  2. 遇到\('B'\)则将当前点的\(dfn\)从\(bit\)(或线段树)中删除;
  3. 否则往下跳,并将该节点插入\(bit\)(或线段树);
//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#define N (100010)
using namespace std;

char s[N];

struct Trie{
  int size,root;
  int son[N][26],fail[N];
  int val[N],n,fa[N],ans[N];

  void init(){ size=1,root=0; }

  void insert(){
    int cur=root;
    for(int i=0;s[i];i++){
      if(s[i]=='P') val[++n]=cur;
      else if(s[i]=='B') cur=fa[cur];
      else{
    int id=s[i]-'a';
    if(!son[cur][id]) son[cur][id]=size++;
    fa[son[cur][id]]=cur,cur=son[cur][id];
      }
    }
  }

  int num,head[N],nxt[N],to[N];
  void add(int u,int v){
    nxt[++num]=head[u];to[num]=v;head[u]=num;
  }

  void build(){
    int que[N];
    int hd=0,tl=0;
    for(int i=0;i<26;i++)
      if(son[root][i]){
    que[tl++]=son[root][i];
    fail[son[root][i]]=root;
      }
      else son[root][i]=root;

    while(hd<tl){
      int cur=que[hd++];
      for(int i=0;i<26;i++){
    int Son=son[cur][i];
    if(Son){
      int f=fail[cur];
      while(f&&!son[f][i]) f=fail[f];
      fail[Son]=son[f][i];
      que[tl++]=Son;
    }
    else son[cur][i]=son[fail[cur]][i];
      }
    }
    for(int i=1;i<size;i++) add(fail[i],i);
  }

  int st[N],ed[N],tim,t[N];
  void dfs(int x){
    st[x]=++tim;
    for(int i=head[x];i;i=nxt[i]) dfs(to[i]);
    ed[x]=tim;
  }

  int lowbit(int x){return x&-x;}
  void up(int x,int val){for(;x<=tim;x+=lowbit(x))t[x]+=val;}
  int Q(int x){int ret=0;for(;x;x-=lowbit(x))ret+=t[x];return ret;}

  struct node{ int x,id; }; vector<node>p[N];

  void Ans(){
    int m; scanf("%d",&m);
    for(int i=1;i<=m;i++){
      int x,y; scanf("%d%d",&x,&y);
      p[val[y]].push_back((node){x,i});
    }
    int x=0;
    for(int i=0;s[i];i++){
      if(s[i]=='P')
    for(int j=0,l=p[x].size();j<l;j++){
      int X=p[x][j].x,ID=p[x][j].id;
      ans[ID]=Q(ed[val[X]])-Q(st[val[X]]-1);
    }
      else if(s[i]=='B') up(st[x],-1),x=fa[x];
      else x=son[x][s[i]-'a'],up(st[x],1);
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
  }

}AC;

void init(){ AC.init(); scanf("%s",s); AC.insert(); AC.build(); }

void work(){ AC.dfs(0); AC.Ans(); }

int main(){ init(); work(); return 0; }

沉迷AC自动机无法自拔之:[BZOJ2434] [Noi2011] 阿狸的打字机的更多相关文章

  1. 沉迷AC自动机无法自拔之:穿越广场 square

    如标题所言,我已经沉迷于AC自动机无法自拔了... 这又是一道AC自动的题,红红火火恍恍惚惚 穿越广场 [问题描述] L 国的仪仗队要穿越首都广场了.首都广场可以看做是一块 N*M 的矩形网格,仪仗队 ...

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

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

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

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

  4. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

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

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

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

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

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

  7. 沉迷AC自动机无法自拔之:[UVALive 4126] Password Suspects

    图片加载可能有点慢,请跳过题面先看题解,谢谢 一看到这么多模式串就非常兴奋,又是\(AC\)自动机 题目就是要求:经过 \(n\) 个节点,把所有单词都遍历一遍的方案数,和那道题差不多嘛 所以这样设: ...

  8. 沉迷AC自动机无法自拔之:[UVA 11468] Substring

    图片加载可能有点慢,请跳过题面先看题解,谢谢 这个鬼题目,上一波套路好了 先用题目给的模板串建\(AC\)自动机,把单词结尾标记为 \(val=1\),然后在建好的\(AC\)自动机上跑 \(dp\) ...

  9. BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)

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

随机推荐

  1. .NET Core 3.0 跟踪

    Preview1: https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-net-core-3-preview-1-and-ope ...

  2. Task 异步编程测试案例及基础应用说明

    对于多线程,我们经常使用的是Thread.在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于“任务的编程模型”所冲击,因为tas ...

  3. SC1243sensor噪点问题调试

    接手一块SC1243sensor的板子调试,仔细核对了原理图和PCB发现,PCB不是很好,电源处理不够好,但是出图了,问题是有噪点,麻点,根据经验要求软件修改了PCLK的极性噪点消失,问题解决. 1: ...

  4. Centos7.2下OpenVPN 环境完整部署记录

    关于OpenVPN的有关介绍及为何使用OpenVPN在此就不做赘述了,下面直接记录Centos7.2系统下部署OpenVPN环境的操作过程: 1) 先将本机的yum换成阿里云的yum源 [root@t ...

  5. Stanford Word Segmenter的特定领域训练

    有没有人自己训练过Stanford Word Segmenter分词器,因为我想做特定领域的分词,但在使用Stanford Word Segmenter分词的时候发现对于我想做的领域的一些词分词效果并 ...

  6. BUAAMOOC项目终审报告

    工作总结 我们是歪果仁带你灰开发团队.我们开发的项目是北航学堂(MOOC)的android客户端:BUAAMOOC. 目前我们完成了主要功能,包括UI设计,视频播放,视频下载,学习进度,个人信息等功能 ...

  7. linux内核分析第五次实验

    给MenuOS增加time和time-asm命令 上周是从用户态的观点来理解系统调用,这周从内核态出发研究系统调用,通过跟踪调试,首先把上周的两个命令加到MenuOS中: rm menu -rf 强制 ...

  8. 《Linux内核设计与实现》读书笔记六

    第4章 进程调度35 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有通过调度程序的合理调度,系统资源才能最 ...

  9. Ubuntu 服务器指南

    https://help.ubuntu.com/lts/serverguide/   Jabber Instant Messaging Server https://help.ubuntu.com/l ...

  10. CentOS 7 Install Adobe Flash Player

    From Officail Adobe Flash Site don't down (YUM )adobe-release-x86_64-1.0-1.noarch.rpm,but to downloa ...