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


    [NOI2011] 阿狸的打字机

    题目描述:

    阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。

    打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。经阿狸研究发现,这个打字机是这样工作的:

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

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

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

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

    a aa ab

    我们把纸上打印出来的字符串从1开始顺序编号,一直到n。

    打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,

    在小键盘上输入两个数(x,y)(其中(1 <= x,y <= n)),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

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

    输入格式:

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

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

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

    输出格式:

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

    数据范围:

    (n,m<= 10^{5}) 

     

    首先,如果模拟按键的过程(暂时无视询问),把所有操作后的串都提取出来

    可以形成一棵Trie树

    题目中又正好提到了匹配,那么不妨继续建出AC自动机

    如果对AC自动机有了解,那么不难知道一个点及其fail后继有多少点被标记,那么它代表的串出现的次数就是被标记的点数

    因此,如果把AC自动机的fail树拿出来,原问题可以转化为:

    维护一棵树,支持:

    给定一堆被标记的点,查询一个点的子树内被标记的点的个数

    这是不可做的

    但是,原问题有特殊性

    这些被标记的点是1个1个标记的,因此,我们可以离线根据x排序

    那么,现在我们可以再模拟一遍,当模拟到x次操作时,就可以回答跟x有关的回答了。

    注意到原问题转化后相当于要支持:单点修改,子树查询

    拿树状数组维护dfs序就能解决这个问题。

    复杂度O((m log n))

    代码在此

  • 相关阅读:
    在线图片压缩
    wiki-editor语法
    Android 4.0.4模拟器安装完全教程(图文)
    Javascript中的void
    守护进程
    jQuery编程的最佳实践
    JavaScript内存优化
    vim编程技巧
    MySQL表的四种分区类型
    SQL中的where条件,在数据库中提取与应用浅析
  • 原文地址:https://www.cnblogs.com/reverymoon/p/8874039.html
Copyright © 2020-2023  润新知