LeetCode 1048. 最长字符串链

106 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情

一、题目描述:

1048. 最长字符串链 - 力扣(LeetCode)

给出一个单词数组 words ,其中每个单词都由小写英文字母组成。

如果我们可以 不改变其他字符的顺序 ,在 wordA 的任何地方添加 恰好一个 字母使其变成 wordB ,那么我们认为 wordA 是 wordB 的 前身 。

  • 例如,"abc" 是 "abac" 的 前身 ,而 "cba" 不是 "bcad" 的 前身

词链是单词 [word_1, word_2, ..., word_k] 组成的序列,k >= 1,其中 word1 是 word2 的前身,word2 是 word3 的前身,依此类推。一个单词通常是 k == 1 的 单词链 。

从给定单词列表 words 中选择单词组成词链,返回 词链的 最长可能长度 。  

示例 1:

输入:words = ["a","b","ba","bca","bda","bdca"]
输出:4
解释:最长单词链之一为 ["a","ba","bda","bdca"]

示例 2:

输入:words = ["xbc","pcxbcf","xb","cxbc","pcxbc"]
输出:5
解释:所有的单词都可以放入单词链 ["xb", "xbc", "cxbc", "pcxbc", "pcxbcf"].

示例 3:

输入:words = ["abcd","dbqca"]
输出:1
解释:字链["abcd"]是最长的字链之一。
["abcd""dbqca"]不是一个有效的单词链,因为字母的顺序被改变了。

提示:

  • 1 <= words.length <= 1000
  • 1 <= words[i].length <= 16
  • words[i] 仅由小写英文字母组成。

二、思路分析:

dp[i]定义为以i位置的字符串为词链的最后一个单词可以构成的词链的最大长度。
状态转移方程为dp[i] = max(dp[i], dp[j] + 1)
其中,dp[j]为第i个字符串之前为其前身的字符串可以构成词链的最大长度。
同时对字符串按长度进行排序,保证可以遍历所有的前身。并且定义的dp状态保证了无后效性。

三、AC 代码:

class Solution {
public:
    bool isFormer(string a, string b){
        int flag = 0;
        for(int i = 0, index = 0; i < b.size(); i++, index++){
            if(b[i] != a[index]){
                if(!flag){
                    i--;
                    flag = 1;
                }else{
                    return false;
                }
            }
        }
        return true;
    }
    int longestStrChain(vector<string>& words) {
        int len = words.size();
        sort(words.begin(), words.end(),[](const string& a, string& b){
            return a.size() < b.size();
        });
        vector<int> dp(len, 1);
        for(int i = 0; i < len; i++){
            for(int j = 0; j < i; j++){
                if(words[j].size() == words[i].size() - 1 && isFormer(words[i], words[j])){
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
        }
        return *max_element(dp.begin(), dp.end());
    }   
};