#0005.「NOI2011」阿狸的打字机

题目大意:

  题目为了减少输入量采用了不太直接的输入方法,但这道题的本质还是给定n个字符串,查询x在y中出现的次数。

题目解法:

  看到字符串匹配想到AC自动机。做法上显然是在遍历一遍树的时候处理出所有答案。

  然后其实就是和洛谷上的板子题AC自动机二次加强版差不多了。我们将遍历时的字符串作为动态的文本串。显然,对于任意一个点i的答案只需要在其父亲节点的基础上更新与当前后缀相同的前缀即可。已知与当前节点后缀相同的最长前缀为fail[i],显然我们要更新的是整个fail链(i,fail[i],fail[fail[i]],...,0)的答案。我们令一个点i对应的前缀在当前文本串中出现的次数为res[i]。考虑到每个i只有一个固定的fail[i],建立fail树,每个fail[i]到i有一条边。这样我们在更新时就只需要更新i一个点而非整条链。而查询的时候我们只需要查询这个点的子树和即可(因为根据fail树的建边原则,每个点被更新时它到根的路径上的所有点都理应被更新,也就是说对于任意一个点它的子树的更新都会对当前点的答案作出贡献)。回想二次加强板,因为只有一个查询直接算出子树大小即可。而这里我们是动态的,所以需要不断地单点更新,区间求和。因此用bit优化。鉴于要使用bit求子树和,我们要先把fail树按dfs序排好并处理出子树大小。

  另注意在遍历时勿忘回溯(bit)

  窝AC自动机学的好差啊为什么我一直觉得它是用来做单个模式串匹配多个文本串的最诡异的是窝洛谷AC自动机二次加强版明明都A了……

posted @ 2020-05-13 12:04  Myrcella  阅读(108)  评论(0)    收藏  举报