$”abeaBaPcaPBP”$,给一个字符串,小写字母表示输入一个字符在一行,$P$代表打印当前字符串并且换行,$B$表示删除当前字符。$(len\leq 10^5)$
有$q$个询问,询问第$x$字符串在第$y$个字符串出现了几次。$(q\leq 10^5)$
P2414
首先可以将所以字符建立AC自动机,建立好$fail$边。
对于问题:第$x$字符串在第$y$个字符串出现了几次,因为AC自动机记录字符串前缀,暴力做法就是遍历$Y$的每个前缀,在跳$fail边$的时候是否跳到过过$x$这个字符串。
对于$fail$边,就建立$fail$树,那么问题就转换为以$x$最后一个字符为根的的$fail$子树有多少$y$的字符的节点。
如果每次询问都这么做显然复杂度过低,在让$y$节点$size+1$的过程中,其实也对其他节点(包含$y$)$+1$,由于打印性质。只需要重新再现打印过程,打出一个节点的时候$y$终点,计算它对所有$x$,$”B”建$就是删除之前节点的影响。用树状数组维护即可。
CF1207G
题意只是在原题上打字,改成$str[i]=str[x]+c$。
把询问和原来的字符串全部,建立好$fail$边,再现打印过程,只需要建立各个字符串的父子关系,跑一边$dfs$,回溯式:跑完就删除,对之后$y$计算不会产生影响。(好理解的话,就是$dfs$到某个$i$字符串终点时,只有它自己的节点是$+1$)。
代码
1 |
|
1 |
|