题目描述:
给出一个单词列表,其中每个单词都由小写英文字母组成。
如果我们可以在 word1 的任何地方添加一个字母使其变成 word2,那么我们认为 word1 是 word2 的前身。例如,“abc” 是 “abac” 的前身。
词链是单词 [word_1, word_2, …, word_k] 组成的序列,k >= 1,其中 word_1 是 word_2 的前身,word_2 是 word_3 的前身,依此类推。
从给定单词列表 words 中选择单词组成词链,返回词链的最长可能长度。
示例:
输入:[“a”,“b”,“ba”,“bca”,“bda”,“bdca”]
输出:4
解释:最长单词链之一为 “a”,“ba”,“bda”,“bdca”。
提示:
1 <= words.length <= 1000
1 <= words[i].length <= 16
words[i] 仅由小写英文字母组成。
方法1:
主要思路:解题汇总链接
(1)动态规划;
(2)先将原数组使用字符串的长度进行排序;
(3)然后遍历排序后的数组,将字符串放入动态存储数据结构unordered_map<string,int>来存储使用当前字符串作为链的结尾字符串,能够获得最长的链的长度;
(4)对于每个当前的字符串,找出各个长度减1的子字符串,然后判断该字符串是否存在于dp中,若存在,则更新可能的长度;
class Solution {
public:
int longestStrChain(vector<string>& words) {
sort(words.begin(),words.end(),[](string&lhs,string&rhs){//根据字符串的长度进行排序
return lhs.size()<rhs.size();
});
unordered_map<string,int> dp;//存储以各个字符串作为链的尾部字符串的最长长度
int max_len=1;
for(string&word:words){//遍历各个字符串
dp[word]=1;//初始化
int len=word.size()-1;//前一个字符串的长度
if(len==0){
continue;
}
//获得各个可能的组成的子字符串
for(int i=0;i<=len;++i){
string sub=word.substr(0,i);
sub+=word.substr(i+1,len-i);
if(dp.count(sub)){//若存在子字符串,则更新
dp[word]=max(dp[word],dp[sub]+1);
}
}
max_len=max(max_len,dp[word]);//更新最长的长度
}
return max_len;
}
};