1048. 最长字符串链

题目描述

给了一个单子数组words
给了字母前身的定义:A在任何地方加一个字符,凑成B,A就是B的前身
问从words中怎么选,能构成最长的词链?

f1-记忆化搜索

基本分析

  1. 怎么找到子问题?假如s是词链的最后一个单词,那么枚举去掉s某位后的构成新的词s-1,s-1就是s的更小一级的子问题
  2. dfs怎么实现?传入参数:s就行了;结束条件?长度是1的时候返回1;
  3. 为啥要记忆化?可能去掉某个字符后会重复,减少计算

代码

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)

总结

  1. 能找到子问题
  2. 从定到更小的问题是递,从小的问题返回结果是归

f2-dp

基本分析

  1. 怎么找到递推的规律?对某个字符s来说,他的结果是之前mp[s-1]的最大值+1
  2. mp[s-1]从哪里来?定义一个字典专门来存
  3. 按照什么顺序递推?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())
            

总结

  1. 能找到递推的规律,这里不是看前一个和当前字符的关系,而是枚举当前字符s去掉后的在不在之前的结果中
posted @ 2023-04-27 20:22  zhangk1988  阅读(12)  评论(0编辑  收藏  举报