题目描述
给了一个单子数组words
给了字母前身的定义:A在任何地方加一个字符,凑成B,A就是B的前身
问从words中怎么选,能构成最长的词链?
基本分析
- 怎么找到子问题?假如s是词链的最后一个单词,那么枚举去掉s某位后的构成新的词s-1,s-1就是s的更小一级的子问题
- dfs怎么实现?传入参数:s就行了;结束条件?长度是1的时候返回1;
- 为啥要记忆化?可能去掉某个字符后会重复,减少计算
代码
class Solution:
def longestStrChain(self, words: List[str]) -> int:
ws = set(words)
@cache
def dfs(s):
cnt = 0
for i in range(len(s)):
prev = s[:i] + s[i+1:]
if prev in ws:
cnt = max(cnt, dfs(prev))
return cnt + 1
return max(dfs(word) for word in words)
总结
- 能找到子问题
- 从定到更小的问题是递,从小的问题返回结果是归
基本分析
- 怎么找到递推的规律?对某个字符s来说,他的结果是之前mp[s-1]的最大值+1
- mp[s-1]从哪里来?定义一个字典专门来存
- 按照什么顺序递推?words排序,从小到大
代码
class Solution:
def longestStrChain(self, words: List[str]) -> int:
words.sort(key = len)
# 记录某个字符能对应的最长结果
mp = dict()
for s in words:
cnt = 0
for i in range(len(s)):
cnt = max(cnt, mp.get(s[:i] + s[i+1:], 0))
mp[s] = cnt + 1
return max(mp.values())
总结
- 能找到递推的规律,这里不是看前一个和当前字符的关系,而是枚举当前字符s去掉后的在不在之前的结果中