1048. 最长字符串链
题目描述
给出一个单词数组 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、首先将所给的串按照从短到长进行排序,然后将相同长度的串加入到对应的二维数组中去
2、将最短的串的dp值初始化为1
3、循环查找比当前串长度少一的串,如果是其前身则,dp[当前串] = max(dp[当前串] ,dp[前身]+1)
4、返回最大的dp值即可
class Solution {
public:
static bool cmp(string s1, string s2){
return s1.length() < s2.size();
}
//比较函数,如果s1 是 s2的前身则返回true,否则返回false
bool count(string s1,string s2){
int i = 0 , j = 0;
while(i < s1.length() && j <s2.length()){
if(s1[i] == s2[i+j]){
i++;
}else{
j++;
}
if(j > 1){
return false;
}
}
return true;
}
int longestStrChain(vector<string>& w) {
int ans = 1;
sort(w.begin(),w.end(),cmp);
int len = w.size();
//mp数组将 不同长度的串分类
unordered_map<int,vector<string>> mp(17);
vector<int>dp(len+1);
mp[w[0].size()].push_back(w[0]);
for(int i = 1 ; i < len ;i++){
mp[w[i].size()].push_back(w[i]);
}
int x = 0,tp = 1,tmax = 1;
while(x < len){
//tp 用于加速查找,如果找到前身的最大值,则停止查找
tp = tmax;
int leng = mp[w[x].size()].size();
//初始化
if(x == 0){
for(int j = 0 ; j < mp[w[x].size()].size();j++){
dp[j] = 1;
}
}else{
for(int j = 0 ; j < leng ;j++){
dp[x+j] = 1;
for(int i = x-1;i >= 0;i--){
//在长度等于当前串长度减一的串中寻找,如果能找到前
//身,则当前串的dp值为 dp[前身]+1;否则当前串的值为 1
if( w[i].size() < w[x+j].size()-1){
break;
}else if(count(w[i],w[x+j])){
//找到前身
dp[x+j] = max(dp[x+j],dp[i]+1);
if(dp[x+j] > ans){
//更新返回值
ans = dp[x+j];
}
//更新当前层的最大值
if(tmax < dp[x+j]){
tmax = dp[x+j];
}
//如果前身的dp值,为当前串的所有可能的前身中值最大的,则跳出循环
if(dp[x+j] == tp+1){
break;
}
}
}
}
}
x += leng;
}
// for(auto h : dp){
// cout<<h<<" ";
// }
// cout<<endl;
return ans;
}
};