描述

最长回文子列(非字串, dp遍历方向) - 图1

反向遍历

  1. # input: abcda output: 3(aca)
  2. def MaxPalindromixSub(s: str):
  3. # dp[i][j] s[i, j]闭区间内的最长回文子列,
  4. # 注意dp数组遍历的方向
  5. dp = [[0 if i != j else 1 for j in range(len(s))] for i in range(len(s))]
  6. for row in dp:
  7. print(row)
  8. # 反向遍历: 从最后一行开始
  9. for i in range(len(s) - 1, -1, -1):
  10. for j in range(i + 1, len(s)):
  11. if s[i] == s[j]:
  12. dp[i][j] = 2 + dp[i + 1][j - 1]
  13. else:
  14. dp[i][j] = max(
  15. dp[i][j - 1],
  16. dp[i + 1][j]
  17. )
  18. for row in dp:
  19. print(row)
  20. if __name__ == '__main__':
  21. MaxPalindromixSub('aba')
  • base case

[1, 0, 0]
[0, 1, 0]
[0, 0, 1]

  • output

[1, 1, 3]
[0, 1, 1]
[0, 0, 1]

斜着遍历

  1. # 斜着遍历, 替换上面的双重for, 结果是一样的.
  2. for k in range(1, len(s)): # 第几斜【1,】 主对角线是base case 不用遍历
  3. j = k # 初始化 列标
  4. for i in range(0, len(s) - k):
  5. if s[i] == s[j]:
  6. dp[i][j] = 2 + dp[i + 1][j - 1]
  7. else:
  8. dp[i][j] = max(
  9. dp[i][j - 1],
  10. dp[i + 1][j]
  11. )
  12. j = j + 1

总结

  • dp数组的遍历方向可能不同 正的 反的 斜的

    • 可以根据base base 来分析
  • 还可以根据最长公共子列的方法来分析(正序, 倒序)