AGC022
https://atcoder.jp/contests/agc022/tasks
E - Median Replace
先考虑如何判断合法性。显然可以贪心的把 \(000\) 删去两个 \(0\),然后删去剩下的相邻的 \(01\),看最后是否剩下 \(1\),第二步可以看作比较剩下的 \(0,1\) 个数
尝试构建成一个 DFA。使用栈维护前面剩下的 \(0,1\),考虑转移:
- 添加 \(0\):
- 栈顶为 \(0\):如果栈顶有两个 \(0\) 那么
pop
,否则push(0)
- 栈顶为 \(1\):直接
push(0)
- 栈顶为 \(0\):如果栈顶有两个 \(0\) 那么
- 添加 \(1\):
- 栈顶为 \(0\):此时栈顶的这一段 \(0\) 不可能再形成 \(000\),可以直接按 \(01\) 删除,即
pop
- 栈顶为 \(1\):直接
push(1)
- 栈顶为 \(0\):此时栈顶的这一段 \(0\) 不可能再形成 \(000\),可以直接按 \(01\) 删除,即
通过转移可以看出:任意时刻栈中从底到顶一定是一段 \(1\) 一段 \(0\),且 \(0\) 的个数 \(<3\)。由于最后剩下的 \(1\) 比 \(0\) 多就合法,栈底的 \(1\) 只需要保存 \(\le3\) 个,且二元组 \((1\text{的个数},0\text{的个数})\) 就能唯一确定 DFA 上状态
最终 DFA 的状态数为 \(12\),时间复杂度 \(O(n)\)。大力手玩可以进一步减小 DFA 状态数