区间 DP 与状态机 DP

区间 DP 与状态机 DP 的识别、模板和样例:最长回文子串、股票持股状态等。

#resource / algorithm #type / concept #status / growing #algo / dp

[!info] related notes 算法面试题型 MOC 动态规划 最长回文子串 最长回文子序列 买卖股票的最佳时机 股票最大资产

区间 DP 与状态机 DP

1. 区间 DP

一页式速查表

小类常见状态转移关键词入门题进阶题
区间真假 / 长度dp[i][j]看内部区间[[longest-palindromic-substring最长回文子串]]
区间最优值dp[l][r]枚举最后一步 / 分割点回文类[[burst-balloons
状态机两状态dp[i][state]持股 / 不持股[[best-time-to-buy-and-sell-stock股票入门]]
状态机多状态dp[i][state]冷冻 / 交易次数 / 多状态切换[[best-time-to-buy-and-sell-stock-with-cooldown冷冻期]]

一句话

当状态和区间 [l, r] 有关时,通常考虑区间 DP。

识别信号

  • 子串 / 子数组 / 子区间
  • 要判断整个区间是否满足某性质
  • 要合并区间、切开区间、枚举分割点

常见状态

dp[l][r] = 区间 [l, r] 的最优值 / 是否满足条件

最常见顺序

按区间长度从小到大。

样例:最长回文子串

题目:最长回文子串

状态

dp[i][j] 表示 s[i...j] 是否为回文串。

转移

dp[i][j] = (s[i] === s[j]) && (j - i <= 1 || dp[i + 1][j - 1])

为什么这样遍历

因为依赖内部更短的区间 dp[i + 1][j - 1],所以要先算短区间,再算长区间。

高频坑

  • 没按区间长度枚举,导致依赖项还没算出来
  • 忘了处理长度为 1 或 2 的小区间边界

2. 状态机 DP

一句话

如果题目里“每一步 / 每一天”有若干种状态,并且状态之间会切换,就考虑状态机 DP。

识别信号

  • 股票买卖
  • 今天能做几种动作
  • 当前是否持有、是否冷冻、是否刚卖出

典型状态

dp[i][0] = 第 i 天结束后不持股的最大收益
dp[i][1] = 第 i 天结束后持股的最大收益

基础股票转移

dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
dp[i][1] = max(dp[i - 1][1], -prices[i])

如果有限制(手续费、冷冻期、最多交易 k 次),就在状态维度里继续加条件。

样例:股票最大资产

题目:[[interview-max-asset-stock-trading|股票最大资产]]

这类题的关键不是“当前位置选或不选”,而是:

  • 当前持有多少股 / 是否持股
  • 今天买、卖、还是不动

高频坑

  • 状态定义不完整,导致转移写不全
  • 把“今天结束后的状态”误写成“今天开始前的状态”
  • 忘记给非法状态初始化成负无穷

推荐继续练

创建于 2026/3/18 更新于 2026/5/27