专栏文章

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

P9753题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minid48j
此快照首次捕获于
2025/12/02 02:54
3 个月前
此快照最后确认于
2025/12/02 02:54
3 个月前
查看原文

P9753 [CSP-S 2023] 消消乐

做法一:哈希 + 栈
考虑用栈来刻画合法子串。
枚举起始点,用栈扫一遍,记录出现了几次空栈,即可做到 O(n2)O(n^2)5050 pts。
考虑优化,尝试能否只扫一遍就计算出答案。
假设当前栈状态为 ss,然后让 ss 按顺序接受一个合法串 tt,看一下接受后的 ss 是什么样的,
  • t=2|t|=2,显然 ss 不变。
  • t>2|t|>2 时,归纳假设:任意长度 <t<|t| 的合法串的入栈都不会使 ss 改变。
    • t=c1+a+c2t=c_1+a+c_2,其中 c1c_1c2c_2 为两个相等的字符,aa 为任意合法串。
      • c1c_1 入栈时,若和栈顶元素抵消,由于 aa 不会使 ss 改变,那么 c2c_2 将会补回抵消的 c1c_1,因此 ss 不变。
      • c1c_1 入栈时,若没有和栈顶元素抵消,由于 aa 不会使 ss 改变,那么 c2c_2 将会和 c1c_1 抵消,因此 ss 不变。
    • t=b1+b2++bkt=b_1+b_2+\cdots+b_k 时,其中 bib_i 为任意合法串。显然 ss 不变。
综上所述,ss 接受一个合法串后不会改变状态。
那么反过来归纳一下,假设任意长度 <t<|t| 且不会改变 ss 的串一定是合法串,
  • t=2|t|=2 显然成立。
  • t>2|t|>2 时,
    • 显然 tt 一定存在相邻两个相等的字符。
    • tt 中任意两个相邻相等的字符删去得到 tt'tt' 的能使栈状态不变,根据归纳假设,tt' 是合法串。
    • 显然在合法串任意位置中加入两个相邻相等的字符后还是合法串。
于是可证这个条件是充要的。也就是说,我们从 11 扫到 nn 时,对于两个位置的状态相等的栈,中间一定存在一个合法子串。
于是我们 哈希 + map 记录扫到每个位置时栈的状态即可,复杂度 O(nlogn)O(n\log n)。单模哈希被卡了,笔者写了双模哈希。

做法二:DP
f(i)f(i) 表示以 ii 结尾的合法子串个数,这个比较容易想到。
考虑转移,f(i)f(g(i)1)+1f(i)\gets f(g(i)-1)+1g(i)g(i) 表示最大的 j<ij<i,使得 [j,i][j,i] 是合法子串。
考虑如何求出 g(i)g(i),令 x=i1x=i-1,若 x>0x>0 就不断使 xg(x)1x\gets g(x)-1,直到 s[x]=s[i]s[x]=s[i],这时 g(i)=xg(i)=x。正确性显然。接下来证明这样跳的复杂度为 O(nΣ)O(n|\Sigma|)参考证明
  • j>ij>i,且以 x=j1x=j-1 为起始点,不断跳到 g(x)1g(x)-1,能跳到 ii
  • 反证法。假设存在 k>jk>j,使得 s[k]=s[j]s[k]=s[j],且 kk 能跳到 ii
  • 显然 s[i+1,j1]s[i+1,j-1]s[i+1,k1]s[i+1,k-1] 都是合法串。
  • 根据 做法一 中证明的结论,可以发现 s[j,k1]s[j,k-1] 是合法串。
  • 因此一定存在 t[j+1,k1]t\in[j+1,k-1],使得 s[t]=s[j]s[t]=s[j],且在合法串 s[j,k1]s[j,k-1] 中,ttjj 是匹配的。
  • 因此 s[j,t]s[j,t] 是合法串。
  • 因此 s[t+1,k1]s[t+1,k-1] 是合法串。
  • 又因为 s[t]=s[j]=s[k]s[t]=s[j]=s[k],于是 kk 最多跳到 tt 就会停止,不会跳到 ii。假设不成立。
  • 综上所述,每个点最多会被每种颜色中的一个点跳到,故复杂度为 O(nΣ)O(n|\Sigma|)
通过简单处理即可做到 O(n)O(n)Code

评论

0 条评论,欢迎与作者交流。

正在加载评论...