状态机思维:从自动机到 DP 抽象
0. 元信息
- 主题路径:
docs/topics/algo-design/subtopics/state-machine-thinking/README.md - 父主题:
algo-design - 主分类:数据结构与算法
- 辅助分类:计算机基础
- 适合对象:掌握递归、DP 基础、BFS;想用更抽象的视角把问题转化为图问题的学习者
- 建议周期:1.5~2 周(每周 8~12 小时)
- 前置知识:
recursion-and-backtracking、greedy-and-dp(部分题目)、Pythoncollections.deque与 BFS - 最终目标:能把中等题抽象成有限状态机,画出状态转移图,选择 DP 或 BFS 实现,并解释为什么该范式最优
1. 学习路线
有限自动机(DFA / NFA)基础
→ 状态、事件、转移、接受态
→ 状态机 → DP:买卖股票 / 打家劫舍
→ 状态机 → BFS:单词接龙 / 拓扑序
→ 多维状态:网格、字符串、图上的 FSM
→ 隐式状态机:把"决策"作为状态
→ 状态压缩 DP(bitmask FSM)
每一步都画状态图。先画图,再写代码。
2. 阶段周数分配
| 阶段 | 1.5 周方案 | 2 周方案 | 备注 |
|---|---|---|---|
| 1. FSM 基础 | 0.5 天 | 1 天 | 状态 + 事件 + 转移 |
| 2. 状态机 → DP | 2 天 | 2.5 天 | 122 / 309 / 188 / 213 / 714 |
| 3. 状态机 → BFS | 1.5 天 | 2 天 | 127 / 433 / 752 |
| 4. 多维状态 FSM | 1 天 | 1.5 天 | 487 / 1186 / 903 |
| 5. 状态压缩 | 1.5 天 | 2 天 | 526 / 847 / 1434 |
| 6. 复盘 + 综合题 | 0.5 天 | 1 天 | 错题重做 + 隐式状态题 |
每天 1.5~2 小时。1.5 周方案聚焦前 4 阶段;2 周方案多 2 天做状态压缩与综合题。
3. 九阶段表(精简)
3.1 核心知识
- FSM(Finite State Machine):状态集合 + 事件 + 转移函数 + 接受态。
- DFA(确定):每个状态对每个事件有唯一转移;NFA(非确定):可以有多个转移。
- 状态机 → DP:状态就是 DP 维度;事件就是转移触发条件;权重就是转移代价。
- 状态机 → BFS:状态是节点;合法转移是边;求最短路径用 BFS / Dijkstra。
- 隐式状态:题目里没明说”状态”二字,但可以抽象为”做完某件事后所处的情形”。
- 多维状态:状态维度可以是 (下标, 选择, 资源);如买卖股票第 i 天持有 / 未持有两个状态。
- 状态压缩:用 bitmask 表示集合;n ≤ 20 比较合适。
3.2 实践产出
- 5 道经典 FSM 入门(LeetCode 122 买卖股票 II、LeetCode 309 含冷冻期、LeetCode 188 买卖股票 IV、LeetCode 714 含手续费、LeetCode 213 打家劫舍 II);
- 3 道 FSM + BFS(LeetCode 127 单词接龙、LeetCode 433 最小基因变化、LeetCode 752 打开转盘锁);
- 3 道多维状态 FSM(LeetCode 487 最大连续 1 的个数 II、LeetCode 1186 删除一次得到子数组最大和、LeetCode 903 DI 序列的有效排列数);
- 2 道状态压缩(LeetCode 526 优美的排列、LeetCode 847 访问所有节点的最短路径)。
3.3 可观察学会标准
- 不看答案在 20 分钟内写出买卖股票 II 的状态机 DP;
- 能把单词接龙抽象成 BFS 图问题;
- 能把”打开转盘锁”的状态空间画出来(4 位 × 10 种 = 10000 节点);
- 能解释为什么 847 题用
dp[mask][i]而不是dp[mask]。
4. 第一周(每天 1.5~2 小时)
Day 1 约定:本计划使用 Python 3.10+。统一格式:
python -X dev -W error -m py_compile foo.py;测试用pytest;BFS 模板用collections.deque。所有代码放进algo-design/fsm/week<N>/目录;每个题目单独.py文件,配套notes/<problem>.md含状态转移图(节点 = 状态,边 = 事件)、复杂度推导、状态空间估算。
| 日 | 任务 | 当天交付 | 自检 |
|---|---|---|---|
| Day 1 | 装 Python 3.11 + pytest + ruff;FSM 入门 2 道:LeetCode 70 爬楼梯(状态机视角)+ 198 打家劫舍(持有 / 不持有两状态) | week1/day1/fsm_intro.py + 状态转移图 | pytest week1/day1/test_fsm.py 2 passed;为 198 题画”持有 / 不持有”两状态转移图 |
| Day 2 | 状态机 DP 入门 3 道:122 买卖股票 II、309 含冷冻期、714 含手续费 | week1/day2/stock_dp.py | pytest week1/day2/test_stock.py 3 passed;LeetCode 3/3 AC;309 题画”持有 / 冷却中 / 可买”三状态图 |
| Day 3 | 状态机 DP 进阶:188 买卖股票 IV(k 笔交易,二维状态 (i, k, hold))、213 打家劫舍 II(环形) | week1/day3/stock_advanced.py | pytest week1/day3/test_advanced.py 2 passed;LeetCode 2/2 AC;188 题记录状态维度 dp[i][k][hold] |
| Day 4 | 状态机 BFS 入门 3 道:127 单词接龙、433 最小基因变化、752 打开转盘锁 | week1/day4/fsm_bfs.py + BFS 状态图 | pytest week1/day4/test_bfs.py 3 passed;LeetCode 3/3 AC;752 题画 4 位 × 10 种 = 10000 节点的状态空间 |
| Day 5 | 多维状态 FSM 入门:487 最大连续 1 的个数 II(dp[i][k])、1186 删除一次得到子数组最大和 | week1/day5/multidim_fsm.py | pytest week1/day5/test_multidim.py 2 passed;LeetCode 2/2 AC;记录状态维度 dp[i][used] |
| Day 6 | 状态压缩 DP:526 优美的排列、847 访问所有节点的最短路径 | week1/day6/bitmask_fsm.py | pytest week1/day6/test_bitmask.py 2 passed;LeetCode 2/2 AC;估算 n × 2^n 状态数(n=15 时 491520) |
| Day 7 | 步骤 A:完成 122 买卖股票 II 的完整状态机推导(两状态 + 转移 + base case + 空间优化到 O(1));步骤 B:补齐 4 类边界(空数组 / 单天价格 / 全跌 / 全涨) | week1/day7/stock_ii.py + 4 类边界日志 | pytest -k test_stock_ii 4 个用例全过;每类边界用例的输入/期望/实际写到 notes/week1-day7.md |
Day 7 执行次序
步骤 A —— 买卖股票 II 完整版(60~90 分钟)
- 写二维 DP
dp[i][hold](i=天数,hold=0/1); - 画状态转移图(两状态);
- 压一维 → 滚动变量;
- 跑空 / 单天 / 全涨 / 全跌 4 类数据;
- 对比 O(n) 空间与 O(1) 空间耗时。
步骤 B —— 4 类边界用例(30~45 分钟)
| # | 用例 | 期望行为 | 验证命令 |
|---|---|---|---|
| B1 | 空数组 [] | 返回 0 | pytest -k test_empty |
| B2 | 单天价格 [5] | 返回 0 | pytest -k test_single |
| B3 | 全跌 [7,6,4,3,1] | 返回 0 | pytest -k test_falling |
| B4 | 全涨 [1,2,3,4,5] | 返回 4(差值累加) | pytest -k test_rising |
Day 7 当天必完成步骤 A;步骤 B 至少完成 B1、B4。
5. 阶段通用验收(精简)
- 不看答案重写 10 道 FSM 题;
- 用自己的话解释 FSM、DP、BFS 三者关系;
- 画出每道题的状态转移图(节点 = 状态,边 = 事件 / 转移);
- 测试最小输入、最大输入、特殊情况(空、所有合法、全部非法);
- 至少准备 3 组自定义数据贴出实际输出;
- 记录每题时间空间复杂度;
- 能给现有 FSM 加新状态或新转移。
6. 最终验收
-
独立实现:5 道状态机 DP(122 / 309 / 188 / 213 / 714)、3 道状态机 BFS(127 / 433 / 752)、3 道多维状态(487 / 1186 / 903)、2 道状态压缩(526 / 847);
-
至少完成 13 道题(LeetCode / CSES / AtCoder),分布建议:
子阶段 题目数量 难度分布 平台建议 状态机 DP 入门 5 道 2 Easy + 3 Medium LeetCode 122 / 309 / 188 / 213 / 714 状态机 BFS 3 道 1 Medium + 2 Hard LeetCode 127 / 433 / 752 多维状态 FSM 3 道 1 Medium + 2 Hard LeetCode 487 / 1186 / 903 状态压缩 2 道 1 Medium + 1 Hard LeetCode 526 / 847 约束:至少 5 道达到 Medium,至少 3 道达到 Hard;买卖股票 II 必须在 20 分钟内写出 O(1) 空间版本。
-
完成 1 个综合 Python 项目(自带 README,能被他人按文档复现);
-
能用 15 分钟讲清 FSM 五元组、状态机 → DP 转化、状态机 → BFS 转化、
n × 2^n状态数估算、deadends 前置过滤的必要性。
7. 综合项目
首选:状态机算法可视化工具(必做:CLI 输入 + 输出 + 可选 GUI)。
备选:自动评测器(从 LeetCode 拉指定状态机题目的测试用例,本地批量跑、对比时间、生成错题本)。
备选:状态机题模板生成器(给定关键词「买卖股票 / 单词接龙 / 转盘锁」→ 输出 Python 模板)。
状态机算法可视化工具必做要求:
- 输入:stdin 接收题目名(
stock_ii/stock_cooldown/word_ladder/open_lock/ugly_arrangement)+ 数据集(价格数组 / 单词列表 / deadends); - 输出:必输出(1)状态转移图(节点 + 边的文字描述);(2)DP 转移表(每一步状态值);(3)时间 / 空间复杂度 + 实际耗时;(4)BFS 步数(若适用);
- 算法:必须用至少 2 种范式(状态机 DP + 状态机 BFS);
- 进阶可选:matplotlib 画状态转移图 GUI、可对比”贪心 vs 状态机 DP”在 cooldown 题上的差异。
任何综合项目都必须包含:
- 需求说明(含输入输出约定);
- 数据结构与算法选择理由(为何用状态机 DP、为何选这种状态维度);
- 核心模块说明(Solver / Recorder / Renderer 三层);
- 模块化源码(每题单独文件 + 公共 base class);
- 边界测试(空 / 单元素 / 全跌 / 全涨 + deadends 前置过滤);
- 运行说明(
Makefile或清晰的python -m命令); - README(项目介绍、运行步骤、目录结构、复盘);
- notes/ 规范:
| 文件 | 内容 |
|---|---|
notes/design.md | 状态机五元组定义、状态空间估算、算法选型理由 |
notes/test.md | 每组测试数据的输入 / 期望输出 / 实际输出 / 通过情况 |
notes/retrospective.md | 用时、难点、收获、下一步 |
notes/state-diagrams/ | 至少 5 道题的状态转移图(手画 + 程序输出 DOT 文件) |
notes/dp-tables/ | 至少 3 道 DP 题的状态转移表(手画 + 程序填表截图) |
notes/state-space-estimates.md | 每题的 n × 2^n 或 n × k 状态数估算表 |
notes/edge-cases.md | 4 类边界用例的输入 / 期望 / 实际 |
notes/bfs-vs-dp.md | 单词接龙(用 BFS)与股票 II(用 DP)的范式对比 |
本主题贡献
3 职责
- 把”当前处境”显式化为 FSM 五元组 (Q, Σ, δ, q0, F) —— Q 是状态集合(持有 / 未持有 / 冷却中 / 已用过 k 笔交易),Σ 是事件集合(价格数组中每天的 ±),δ 是转移函数(买 / 卖 / 持 / 冷),并区分 Moore 机(状态决定输出) 与 Mealy 机(转移决定输出)在买卖股票系题目上的等价转换。
- 在 DP / BFS 两种实现路径间切换 —— 求最优解用状态机 DP(买卖股票 / 打家劫舍 / DI 序列),求最短转移步数用 BFS(单词接龙 / 最小基因变化 / 转盘锁);用 guard clause 把 deadends 等非法前置状态在 BFS 入队前过滤(
if next_state in deadends: continue),避免把死锁节点加入访问队列。 - 用 Trie(前缀树
node[26]子节点)把单词搜索问题接入 FSM、用 KMP(失败函数next[]数组)把”模式匹配”问题接入 FSM;状态压缩时用 bitmask 表示已访问集合(如 526 优美排列mask & (1<<i)),估算n × 2^n状态数(如 n=15 时 491520)作为”该不该用状压”的判断阈值。
4 交付物
- 13 道题解(5 状态机 DP + 3 BFS + 3 多维 + 2 状态压缩)+ 4 类边界用例日志(空 / 单天价格 / 全跌 / 全涨)。
- 状态机可视化工具(CLI → 状态转移图节点/边表 + DP 转移表每步状态值 + BFS 步数 + deadends 前置过滤后的有效状态空间)。
- 至少 5 道题的状态转移图(手画 + DOT 文件:买卖股票 II 的两状态 / 309 含冷冻期的三状态 / 打家劫舍 II 的环形拆两段 / 转盘锁的 10000 节点 / 526 优美排列的 bitmask)落
notes/state-diagrams/+ 至少 3 道 DP 题的状态转移表落notes/dp-tables/。 - BFS vs DP 范式对比文档
notes/bfs-vs-dp.md(单词接龙用 BFS 因求最短转移、股票 II 用 DP 因求最大累积收益 —— 同为 FSM 抽象,实现路径由”求最短”还是”求最值”决定)。
3 指标
- 20 分钟内独立写出买卖股票 II 的状态机 DP(含 O(1) 空间滚动变量版本,覆盖持有 / 未持有两状态 + 买/卖/持三种转移)。
- 把转盘锁的 4 位 × 10 种 = 10000 节点状态空间手画出来(含 deadends 前置过滤后的实际访问节点数估算,证明 BFS 状态空间不是”无限”)。
- 在 n=15 时估算 bitmask 状态数
n × 2^n = 491520,主动放弃 bitmask 改用多维 DP 维度(说明状态数估算已成为”该不该用状压”的判断本能,而非盲目开1<<n)。
| 阶段 | 角色 | 资料 | 链接 | 用法 |
|---|---|---|---|---|
| 1~2 | 抽象 | Sipser《Introduction to the Theory of Computation》第 1 章 | https://mitpress.mit.edu/9781133187790/ | FSM 形式化(Q, Σ, δ, q0, F) |
| 1~2 | 经典 | CLRS《Introduction to Algorithms》第 4 版第 14、22 章 | https://mitpress.mit.edu/9780262033848/ | DP 与 BFS 章节 |
| 1~2 | 经典 | Hopcroft, Motwani, Ullman《Introduction to Automata Theory》 | https://www.pearson.com/en-us/subject-catalog/p/Pearson-Catalog/p/2000000000 | FSM 标准教材;当字典 |
| 1~3 | 框架 | labuladong 状态机 DP | https://labuladong.online/algo/ | 中文框架化讲解;先自己写再对照 |
| 1~3 | 图解 | CP-Algorithms DP + Graph | https://cp-algorithms.com/ | 英文图解 + 代码;当字典 |
| 1~3 | 刷题 | LeetCode | https://leetcode.cn/ | 中文题库;状态机按 tag 刷 |
| 1~3 | 刷题 | LeetCode Discuss · 状态机 | https://leetcode.com/discuss/ | 题目分类讨论 |
| 1~3 | 训练 | USACO Guide | https://usaco.guide/ | 美国队训练;按难度递进 |
| 2 | 范式 | Halim《Competitive Programming 3》第 4 章 | https://cpbook.net/ | 竞赛实战;当题目反查 |
| 3 | BFS | VisuAlgo BFS 模拟器 | https://visualgo.net/ | BFS 状态空间可视化 |
| 4 | 协议 | Kleppmann《DDIA》Ch.9 | https://dataintensive.net/ | 一致性与共识(含状态机视角) |
| 5 | bitmask | CP-Algorithms Bitmask 章节 | https://cp-algorithms.com/ | 位运算 + 子集枚举 |
许可证提示:CLRS 与 Sipser 自用学习合理引用;不要复制粘贴课后答案到公开仓库。LeetCode 题面版权见 LeetCode Terms of Service——代码自己写,思路可以分享。CP-Algorithms 是 CC BY-SA。默认做法是读思路后自己重写代码,而不是复制 Editorial。
默认使用顺序:先读 Sipser 第 1 章建立 FSM 形式化心智 → 选读 CLRS 第 14、22 章(DP + BFS)→ 用 LeetCode 刷 8 道状态机题(按 tag)→ 用 labuladong / CP-Algorithms 对照 5 道卡住的题 → 实现买卖股票 II / 含 cooldown 完整推导 → 跑 VisuAlgo BFS 模拟器 → 选读 Halim 第 4 章 → 写复盘到 notes/retrospective.md。
8. 推荐开源资料
| 阶段 | 角色 | 资料 | 链接 | 用法 |
|---|---|---|---|---|
| 1~2 | 抽象 | Sipser《Introduction to the Theory of Computation》第 1 章 | https://mitpress.mit.edu/9781133187790/ | FSM 形式化(Q, Σ, δ, q0, F) |
| 1~2 | 经典 | CLRS《Introduction to Algorithms》第 4 版第 14、22 章 | https://mitpress.mit.edu/9780262033848/ | DP 与 BFS 章节 |
| 1~2 | 经典 | Hopcroft, Motwani, Ullman《Introduction to Automata Theory》 | https://www.pearson.com/en-us/subject-catalog/p/Pearson-Catalog/p/2000000000 | FSM 标准教材;当字典 |
| 1~3 | 框架 | labuladong 状态机 DP | https://labuladong.online/algo/ | 中文框架化讲解;先自己写再对照 |
| 1~3 | 图解 | CP-Algorithms DP + Graph | https://cp-algorithms.com/ | 英文图解 + 代码;当字典 |
| 1~3 | 刷题 | LeetCode | https://leetcode.cn/ | 中文题库;状态机按 tag 刷 |
| 1~3 | 刷题 | LeetCode Discuss · 状态机 | https://leetcode.com/discuss/ | 题目分类讨论 |
| 1~3 | 训练 | USACO Guide | https://usaco.guide/ | 美国队训练;按难度递进 |
| 2 | 范式 | Halim《Competitive Programming 3》第 4 章 | https://cpbook.net/ | 竞赛实战;当题目反查 |
| 3 | BFS | VisuAlgo BFS 模拟器 | https://visualgo.net/ | BFS 状态空间可视化 |
| 4 | 协议 | Kleppmann《DDIA》Ch.9 | https://dataintensive.net/ | 一致性与共识(含状态机视角) |
| 5 | bitmask | CP-Algorithms Bitmask 章节 | https://cp-algorithms.com/ | 位运算 + 子集枚举 |
许可证提示:CLRS 与 Sipser 自用学习合理引用;不要复制粘贴课后答案到公开仓库。LeetCode 题面版权见 LeetCode Terms of Service——代码自己写,思路可以分享。CP-Algorithms 是 CC BY-SA。默认做法是读思路后自己重写代码,而不是复制 Editorial。
默认使用顺序:先读 Sipser 第 1 章建立 FSM 形式化心智 → 选读 CLRS 第 14、22 章(DP + BFS)→ 用 LeetCode 刷 8 道状态机题(按 tag)→ 用 labuladong / CP-Algorithms 对照 5 道卡住的题 → 实现买卖股票 II / 含 cooldown 完整推导 → 跑 VisuAlgo BFS 模拟器 → 选读 Halim 第 4 章 → 写复盘到 notes/retrospective.md。
9. 学习资料汇聚(v0.3)
9.1 背景与动机
有限状态机的数学基础是 Kleene 在 1956 年提出的正则表达式与有限自动机等价定理。Mealy(1955)和 Moore(1956)分别提出 Mealy 机与 Moore 机,把”输出”作为转移的一部分。Rabin & Scott 在 1959 年因 NFA 与 DFA 等价证明获 Turing Award。在算法竞赛里,FSM 思维是 2010 年后逐渐成为中等难度题的常见抽象——把”当前处境”显式化能避开暴力枚举。
行业位置:FSM 是协议设计(TCP / TLS 状态机)、正则表达式(DFA 实现)、游戏 AI(敌人状态切换)、编译原理(词法分析)的核心。算法面试里”买卖股票”系列是 FSM DP 的代表。一句话总结:FSM 思维是把”我做完某件事后处在什么情形”显式化,再按情形做决策或搜索。
9.2 概念地图
flowchart LR
State[状态]
Event[事件]
Transition[转移]
Accept[接受态]
DFA[DFA / NFA]
FSMtoDP[FSM → DP]
FSMtoBFS[FSM → BFS]
Multidim[多维状态]
Bitmask[状态压缩]
Stock[买卖股票]
WordLadder[单词接龙]
Lock[转盘锁]
TSP[TSP 状压]
State --> Event
Event --> Transition
Transition --> Accept
DFA --> FSMtoDP
DFA --> FSMtoBFS
FSMtoDP --> Multidim
FSMtoDP --> Bitmask
Stock --> FSMtoDP
WordLadder --> FSMtoBFS
Lock --> FSMtoBFS
Bitmask --> TSP
核心关系:FSM 是底座抽象;DP / BFS 是两种实现路径;多维状态 + 状态压缩是 FSM 在算法竞赛里的扩展形态。
9.3 基础知识讲解
9.3.1 经典论文
| 资料 | 影响 | 建议读法 |
|---|---|---|
| Kleene, Representation of Events in Nerve Nets and Finite Automata(1956) | 正则表达式与有限自动机等价 | 看历史意义 |
| Mealy, A Method for Synthesizing Sequential Circuits(1955) | Mealy 机 | 了解输出作为转移的一部分 |
| Moore, Gedanken-experiments on Sequential Machines(1956) | Moore 机 | 与 Mealy 机对照 |
| Rabin & Scott, Finite Automata and Their Decision Problems(1959) | NFA / DFA 等价 | 看非确定性证明 |
| Aho, Sethi, Ullman Compilers: Principles, Techniques, Tools(Dragon Book) | 词法分析用 DFA | 看正则表达式 → NFA → DFA 构造 |
9.3.2 经典书籍
| 书 | 影响 | 用法 |
|---|---|---|
| CLRS 第 4 版第 14 章 Dynamic Programming 与第 22 章 BFS | FSM DP 与 BFS 视角 | 当 DP / BFS 章节阅读 |
| Sipser Introduction to the Theory of Computation 第 1 章 | FSM 形式化 | 当抽象基础 |
| Hopcroft, Motwani, Ullman Introduction to Automata Theory, Languages, and Computation | FSM 标准教材 | 当字典 |
| Halim Competitive Programming 3 第 4 章 | 竞赛实战 | 当题目反查 |
9.3.3 优秀博客
| 资料 | 特点 | 用法 |
|---|---|---|
| labuladong 状态机 DP | 中文框架 | 当 Cheatsheet |
| CP-Algorithms DP + Graph | 英文图解 | 当字典 |
| LeetCode Discuss · 状态机 | 题目分类讨论 | 看官方 Editorial 优先 |
| AtCoder Editorial | 题目抽象讲解 | 跟比赛读 |
9.3.4 核心人物
| 人物 | 主要影响 | 建议追踪的材料 |
|---|---|---|
| Stephen Kleene | 正则表达式与 FSM 等价 | 1956 论文 |
| George Mealy / Edward Moore | Mealy / Moore 机 | 1955 / 1956 论文 |
| Michael Rabin / Dana Scott | NFA / DFA 等价证明 | 1959 论文,1976 Turing Award |
| John Hopcroft / Jeffrey Ullman | 自动机理论教材 | 三人合著《自动机理论》 |
| 楼天城(楼教主) | 竞赛圈”状态机思维”实战 | Codeforces / Topcoder 题解 |
9.3.5 开发方法
| 方法 | 具体动作 | 何时用 |
|---|---|---|
| State-first | 先列出所有状态,再写转移 | 任何 FSM 题 |
| Transition-diagram | 画有向图:节点 = 状态,边 = 事件 | FSM 入门 |
| DFS-vs-BFS choice | 状态空间小 → DFS;求最短 → BFS | FSM 实现路径 |
| Multidim explosion | 维度乘积太大时考虑降维 | 复杂 FSM |
| Implicit-state search | 把”决策”作为状态的一部分 | 决策类问题 |
| BFS-on-implicit-graph | 把所有合法中间结果当作节点 | 单词接龙 / 转盘锁 |
9.4 经典问题与经典案例
| # | 问题 | 为什么重要 | 最简答案或图示 |
|---|---|---|---|
| 1 | LeetCode 122 买卖股票 II | FSM DP 入门 | 两个状态:持有 / 未持有 |
| 2 | LeetCode 309 含冷冻期 | 三状态 FSM | 持有 / 未持有(冷却中)/ 未持有(可买) |
| 3 | LeetCode 188 买卖股票 IV | k 笔交易 FSM | 二维状态 (i, k, hold) |
| 4 | LeetCode 213 打家劫舍 II | FSM 环形版 | 分两段:偷第一家 / 不偷第一家 |
| 5 | LeetCode 127 单词接龙 | FSM BFS | 状态 = 单词;边 = 差一个字母 |
| 6 | LeetCode 433 最小基因变化 | FSM BFS | 状态 = 基因串;边 = 一个字母变化 |
| 7 | LeetCode 752 打开转盘锁 | FSM BFS | 状态 = 4 位数;边 = ±1 或死锁过滤 |
| 8 | LeetCode 487 最大连续 1 II | 多维 FSM | dp[i][k] = 在 i 位置已用 k 次翻转的最长 |
| 9 | LeetCode 903 DI 序列有效排列 | 隐式 FSM DP | 状态 = 当前 i 与栈深;转移看插入 D / I |
| 10 | LeetCode 526 优美排列 | 状态压缩 DP | 状态 = bitmask 表示已用数字 |
9.5 学习难点
概念难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 状态识别 | 不知道该选哪几个状态 | 把”我做完某件事后处在什么情形”列出来 |
| DFA vs NFA | 选错实现 | NFA 转 DFA 用子集构造;DP 通常是 DFA |
| Moore vs Mealy | 输出在哪一步 | Moore:状态决定输出;Mealy:转移决定输出 |
思维难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 多维状态爆炸 | 状态数 = 维度乘积 | 降维:合并等价状态;用单调性剪枝 |
| 隐式状态 | 题目没说”状态”二字 | 把决策、约束、资源都画成状态 |
| 转移设计 | 不知道事件有哪些 | 把”每一步能做的合法操作”列出来 |
| 状态压缩选择 | 不知道用 bitmask 还是 DP 维度 | 估算状态数:n=20 用 bitmask,n=100 用 DP 维度 |
工程难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| BFS 队列爆 | 状态空间太大 | 加 visited;用双向 BFS |
| DP 状态数太大 | 状态数 = n × k × 2 | 加剪枝;降维;用记忆化 |
| bitmask 操作错误 | 位运算写错 | 用 (1 << i) & mask、`mask |
| 转盘锁死锁 | 跳过 deadends 失败 | BFS 前先把 deadends 加到 visited |
9.6 技术标准与接口
9.6.1 Entity
| 名称 | 版本 / 文档 | 发布组织 | 状态 | 许可证 / 可访问性 |
|---|---|---|---|---|
| CLRS 第 4 版 | 2022 | MIT Press | 主流教材 | 第三方 PDF 公开 |
| Sipser《Theory of Computation》第 3 版 | 2012 | Cengage | 主流教材 | 第三方资源公开 |
Python collections.deque | CPython 3.10+ | PSF | 内建 | PSF License |
| regex(DFA 实现) | re2 / PCRE | 各实现 | 活跃 | BSD / PCRE LICENSE |
9.6.2 Scope
- FSM 适用:协议状态、词法分析、博弈状态、决策序列、网格 / 字符串上的转移。
- 不适用:纯组合数学(用组合公式)、最短路(图算法)。
- 与 DP / BFS 关系:FSM 是抽象;DP / BFS 是实现路径。
9.6.3 Structure
- FSM 五元组:
(Q, Σ, δ, q0, F)—— 状态集、字母表、转移函数、初始状态、接受态。 - DP 视角:状态 = DP 维度;转移 = DP 方程;初始化 = base case。
- BFS 视角:状态 = 节点;边 = 合法转移;距离 = BFS 步数。
9.6.4 Ecosystem
- 工具:
collections.deque(BFS)、functools.lru_cache(DP memo)、re(正则 DFA)。 - 在线评测:LeetCode、AtCoder、Codeforces。
- 训练集:LeetCode 状态机专题、CSES Graph 章节。
9.6.5 Depth Tiers
| 层级 | 能力 | 状态机思维的可观察标准 |
|---|---|---|
| L0 | 知道存在 | 知道 FSM 是显式化”当前处境” |
| L1 | 看得懂示例 | 能读懂别人的状态机代码 |
| L2 | 能正确调用 | 能写买卖股票 / 单词接龙 |
| L3 | 能解释与排错 | 能设计新题的状态空间,选择 DP 或 BFS |
| L4 | 能设计与扩展 | 能把复杂问题抽象成 FSM 并优化状态数 |
本子主题目标:L3。能画状态转移图 + 选择正确实现路径 + 解释空间复杂度即达到。
9.6.6 Source
- CLRS 官网:第 4 版第 14 章 DP。
- Sipser《Theory of Computation》:第 1 章 FSM 形式化。
- CP-Algorithms:BFS / DP 章节。
- 引用版本快照日期:2026-07-30。
10. 常见误区
- 把状态与决策混为一谈;
- 状态维度过细,导致状态空间爆炸;
- BFS 时忘了 visited,死循环或超时;
- 转盘锁题忘了过滤 deadends;
- 买卖股票 II 写成”贪心”——贪心在 cooldown 版会出错;
- 状压 DP 算错状态数(
2^25 = 33554432,n=20 已是 104 万); - 单词接龙用 DFS 而非 BFS,最短路径算错;
- bitmask 操作混淆
1<<i与i; - 多维状态 DP 写出 N 重循环,自己都数不清维度;
- 状态机 DP 写成贪心,遇到边界条件就崩;
- 写完不复盘,下周遇到同类型还是不会。
11. 所有知识点分类
- 编程语言(辅):Python
collections.deque做 BFS、functools.lru_cache做 FSM DP memo、位运算 (1<<i、mask | (1<<i)、mask & ~(1<<i))、set做 BFS visited、re模块(DFA 实现正则)。 - 数据结构与算法(主):FSM 五元组(Q, Σ, δ, q0, F)、DFA / NFA、Mealy / Moore 机、状态机 → DP(买卖股票 / 打家劫舍)、状态机 → BFS(单词接龙 / 转盘锁)、多维状态、状态压缩(bitmask FSM)。
- 计算机基础:正则表达式与有限自动机等价、词法分析(正则 → NFA → DFA 子集构造)、协议状态机(TCP / TLS)、NFA → DFA 转换的子集构造法。
- 工程技术:画状态转移图(节点 = 状态,边 = 事件)、估算
n × 2^n状态数选 DP 或 BFS、双向 BFS 缩小搜索空间、deadends 等非法状态前置过滤。 - Web 与后端:HTTP 协议状态机、TCP 连接状态、正则路由匹配(DFA);本计划不展开。
- 前端与客户端:浏览器事件循环的状态视角、表单状态机;本计划不展开。
- 数据与人工智能:HMM / CRF 序列标注本质是 FSM;本计划不展开。
- 项目与职业能力:LeetCode 122 / 127 / 188 / 213 / 309 / 433 / 487 / 752 / 903 等 FSM 高频面试题、20 分钟写出买卖股票 II 状态机 DP、估算状态空间选择 DP 或 BFS。
本计划归属:数据结构与算法 主 + 编程语言 辅。