You are given an array of words
where each word consists of lowercase English letters.
wordA
is a predecessor of wordB
if and only if we can insert exactly one letter anywhere in wordA
without changing the order of the other characters to make it equal to wordB
.
- For example,
"abc"
is a predecessor of"abac"
, while"cba"
is not a predecessor of"bcad"
.
A word chain is a sequence of words [word1, word2, ..., wordk]
with k >= 1
, where word1
is a predecessor of word2
, word2
is a predecessor of word3
, and so on. A single word is trivially a word chain with k == 1
.
Return the length of the longest possible word chain with words chosen from the given list of words
.
Example 1:
Input: words = ["a","b","ba","bca","bda","bdca"] Output: 4 Explanation: One of the longest word chains is ["a","ba","bda","bdca"].
Example 2:
Input: words = ["xbc","pcxbcf","xb","cxbc","pcxbc"] Output: 5 Explanation: All the words can be put in a word chain ["xb", "xbc", "cxbc", "pcxbc", "pcxbcf"].
Example 3:
Input: words = ["abcd","dbqca"] Output: 1 Explanation: The trivial word chain ["abcd"] is one of the longest word chains. ["abcd","dbqca"] is not a valid word chain because the ordering of the letters is changed.
Constraints:
1 <= words.length <= 1000
1 <= words[i].length <= 16
words[i]
only consists of lowercase English letters.
Companies: Google, Amazon, Lucid, TikTok, MathWorks, Bloomberg, Facebook, Oracle, ByteDance, Flipkart, Apple, Two Sigma, Wix
Related Topics:
Array, Hash Table, Two Pointers, String, Dynamic Programming
Hints:
- Instead of adding a character, try deleting a character to form a chain in reverse.
- For each word in order of length, for each word2 which is word with one character removed, length[word2] = max(length[word2], length[word] + 1).
For each string, if we check its neighbor by adding a letter, there will be (S + 1) * 26
possible neighbors. If we check its neighbor by removing a letter, there will be S
neighbors.
// OJ: https://leetcode.com/problems/longest-string-chain/
// Author: github.com/lzl124631x
// Time: O(N * S^2)
// Space: O(NS)
class Solution {
unordered_map<string, int> m;
int dp(const string &s) {
if (m[s]) return m[s];
if (s.size() == 1) return 1;
int ans = 1;
for (int i = 0; i < s.size(); ++i) {
auto copy = s;
copy.erase(begin(copy) + i);
if (m.count(copy)) {
ans = max(ans, 1 + dp(copy));
}
}
return m[s] = ans;
}
public:
int longestStrChain(vector<string>& A) {
for (auto &s : A) m[s] = 0;
int ans = 0;
for (auto &s : A) {
ans = max(ans, dp(s));
}
return ans;
}
};
// OJ: https://leetcode.com/problems/longest-string-chain/
// Author: github.com/lzl124631x
// Time: O(N * S^2)
// Space: O(NS)
class Solution {
public:
int longestStrChain(vector<string>& A) {
sort(begin(A), end(A), [](auto &a, auto &b) { return a.size() < b.size(); });
unordered_map<string, int> dp;
int ans = 1;
for (auto &s : A) {
dp[s] = 1;
for (int i = 0; i < s.size(); ++i) {
auto next = s.substr(0, i) + s.substr(i + 1);
if (dp.count(next)) {
dp[s] = max(dp[s], dp[next] + 1);
ans = max(ans, dp[s]);
}
}
}
return ans;
}
};