Algorithm


Problem Name: 1048. Longest String Chain

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.

Code Examples

#1 Code Example with Java Programming

Code - Java Programming


class Solution {
  public int longestStrChain(String[] words) {
    Map dp = new HashMap<>();
    Set < String> wordSet = Arrays.stream(words).collect(Collectors.toSet());
    int maxLength = 0;
    for (String word : words) {
      maxLength = Math.max(maxLength, dfs(wordSet, dp, word));
    }
    return maxLength;
  }
  
  private int dfs(Set < String> wordSet, Map dp, String currWord) {
    if (dp.containsKey(currWord)) {
      return dp.get(currWord);
    }
    int maxLength = 1;
    StringBuilder sb = new StringBuilder(currWord);
    for (int i = 0; i  <  currWord.length(); i++) {
      sb.deleteCharAt(i);
      String newWord = sb.toString();
      if (wordSet.contains(newWord)) {
        maxLength = Math.max(maxLength, 1 + dfs(wordSet, dp, newWord));
      }
      sb.insert(i, currWord.charAt(i));
    }
    dp.put(currWord, maxLength);
    return dp.get(currWord);
  }
}
Copy The Code & Try With Live Editor

Input

x
+
cmd
words = ["a","b","ba","bca","bda","bdca"]

Output

x
+
cmd
4

#2 Code Example with Javascript Programming

Code - Javascript Programming


const longestStrChain = function(words) {
  words.sort((a, b) => a.length - b.length)
  const dp = {}
  for(let el of words) {
    dp[el] = 1
  }
  
  let res = Number.MIN_VALUE
  for(let w of words) {
    for(let i = 0; i  <  w.length; i++) {
      let prev = w.slice(0, i) + w.slice(i + 1)
      dp[w] = Math.max(dp[w], (dp[prev] || 0) + 1 )
    }
    if(dp[w] > res) res = dp[w]
  }
  return res
};
Copy The Code & Try With Live Editor

Input

x
+
cmd
words = ["a","b","ba","bca","bda","bdca"]

Output

x
+
cmd
4

#3 Code Example with Python Programming

Code - Python Programming


class Solution:
    def longestStrChain(self, words: List[str]) -> int:
        def dfs(w1, size):
            return max([dfs(w2, size + 1) for w2 in graph[w1]], default = size)
        graph = collections.defaultdict(list)
        for w in words:
            graph[len(w)].append(w)
        for w1 in words:
            for w2 in graph[len(w1) + 1]:
                for i in range(len(w2)):
                    if w2[:i] + w2[i + 1:] == w1:
                        graph[w1].append(w2)
        return max(dfs(w, 1) for w in words)
Copy The Code & Try With Live Editor

Input

x
+
cmd
words = ["xbc","pcxbcf","xb","cxbc","pcxbc"]

Output

x
+
cmd
5

#4 Code Example with C# Programming

Code - C# Programming


using System;
using System.Collections.Generic;
using System.Text;

namespace LeetCode
{
    public class _1048_LongestStringChain
    {
        public int LongestStrChain(string[] words)
        {
            var chainLength = new Dictionary < string, int>();
            var set = new HashSet(words);

            int max = 0;
            foreach (var word in words)
            {
                DFS(word, set, chainLength);
                max = Math.Max(max, chainLength[word]);
            }
            return max;
        }

        private int DFS(string word, HashSet < string> set, Dictionary chainLength)
        {
            if (string.IsNullOrEmpty(word) || !set.Contains(word)) return 0;
            if (chainLength.ContainsKey(word)) return chainLength[word];

            var sb = new StringBuilder(word);
            var max = 0;
            for (int i = 0; i  <  word.Length; i++)
            {
                var ch = sb[i];

                sb.Remove(i, 1);
                max = Math.Max(max, DFS(sb.ToString(), set, chainLength) + 1);
                sb.Insert(i, ch);
            }

            chainLength[word] = max;
            return max;
        }
    }
}
Copy The Code & Try With Live Editor

Input

x
+
cmd
words = ["xbc","pcxbcf","xb","cxbc","pcxbc"]

Output

x
+
cmd
5
Advertisements

Demonstration


Previous
#1025 Leetcode Remove All Adjacent Duplicates In String Solution in C, C++, Java, JavaScript, Python, C# Leetcode
Next
#1049 Leetcode Last Stone Weight II Solution in C, C++, Java, JavaScript, Python, C# Leetcode