题解:P9753 [CSP-S 2023] 消消乐【哈希,DP】

· · 题解

P9753 [CSP-S 2023] 消消乐

做法一:哈希 + 栈

考虑用栈来刻画合法子串。

枚举起始点,用栈扫一遍,记录出现了几次空栈,即可做到 O(n^2)50 pts。

考虑优化,尝试能否只扫一遍就计算出答案。

假设当前栈状态为 s,然后让 s 按顺序接受一个合法串 t,看一下接受后的 s 是什么样的,

综上所述,s 接受一个合法串后不会改变状态。

那么反过来归纳一下,假设任意长度 <|t| 且不会改变 s 的串一定是合法串,

于是可证这个条件是充要的。也就是说,我们从 1 扫到 n 时,对于两个位置的状态相等的栈,中间一定存在一个合法子串。

于是我们 哈希 + map 记录扫到每个位置时栈的状态即可,复杂度 O(n\log n)。单模哈希被卡了,笔者写了双模哈希。

Code

做法二:DP

f(i) 表示以 i 结尾的合法子串个数,这个比较容易想到。

考虑转移,f(i)\gets f(g(i)-1)+1g(i) 表示最大的 j<i,使得 [j,i] 是合法子串。

考虑如何求出 g(i),令 x=i-1,若 x>0 就不断使 x\gets g(x)-1,直到 s[x]=s[i],这时 g(i)=x。正确性显然。接下来证明这样跳的复杂度为 O(n|\Sigma|)。参考证明

Code

通过简单处理即可做到 O(n)。Code