AC自动机和Fail树
萌新第一次试着写博客…全是口胡(/□\*),可能以后也不会有时间再写了
相关数据结构:AC自动机,树状数组(线段树)
Fail指针的基本性质:某只结点的Fail指针,指向它所代表的字符串的最长的后缀的结点。
性质:每只结点沿着其Fail指针一直走,最终会走到根节点。
这样,将每只结点和其Fail指针指向的结点连边,就形成了一个树,其根与原Trie树相同,称为Fail树。
性质:
1 某个结点 A A A,它子树中的所有节点在Trie图中沿Fail指针一直走,会走到 A A A结点,这说明这些结点所代表的前缀都是 A A A的后缀。
2 该结点沿Fail指针向根走,经过的所有结点所代表的串都是该结点 A A A的后缀。
例子:
对每一个模式串 s i s_i si,将它所有前缀所代表的结点的权值 + 1 +1 +1,再求以 A A A为根的子树的权值和,就是 A A A在所有模式串中出现的次数。
具体地,我们可以递归地求权和,也可以用DFS序,求该结点区间的区间和。(单点更新、区间查询)
还记得吗?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 ) (x, y) (x,y)。
输出格式:
输出m行,其中第i行包含一个整数,表示第i个询问的答案。
思考:
本题要求任意一个串在给定的串中的出现次数,可能有100000次询问,AC自动机和KMP等等显然都不行。
根据Fail树的性质,一只以结点 A A A为根的子树中的结点,一定含有 A A A串做后缀。那么如果 A A A是某个串的结束结点,那么 A A A串就在这些结点的串中出现过。那么对于另一个串 B B B,它的结点有多少在 A A A子树中出现,那么 A A A就在 B B