website/content.en/ChapterFour/1000~1099/1048.Longest-String-Chain.md
Given a list of words, each word consists of English lowercase letters.
Let's say word1 is a predecessor of word2 if and only if we can add exactly one letter anywhere in word1 to make it equal to word2. For example, "abc" is a predecessor of "abac".
A word chain is a sequence of words [word_1, word_2, ..., word_k] with k >= 1, where word_1 is a predecessor of word_2, word_2 is a predecessor of word_3, and so on.
Return the longest possible length of a 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 chain is "a","ba","bda","bdca".
Example 2:
Input: words = ["xbc","pcxbcf","xb","cxbc","pcxbc"]
Output: 5
Constraints:
1 <= words.length <= 10001 <= words[i].length <= 16words[i] only consists of English lowercase letters.Given a list of words, each word consists of lowercase English letters. If we can add one letter anywhere in word1 to make it become word2, then we consider word1 to be a predecessor of word2. For example, "abc" is a predecessor of "abac". A word chain is a sequence composed of words [word_1, word_2, ..., word_k], with k >= 1, where word_1 is a predecessor of word_2, word_2 is a predecessor of word_3, and so on. Choose words from the given list words to form a word chain, and return the longest possible length of the word chain.
package leetcode
import "sort"
func longestStrChain(words []string) int {
sort.Slice(words, func(i, j int) bool { return len(words[i]) < len(words[j]) })
poss, res := make([]int, 16+2), 0
for i, w := range words {
if poss[len(w)] == 0 {
poss[len(w)] = i
}
}
dp := make([]int, len(words))
for i := len(words) - 1; i >= 0; i-- {
dp[i] = 1
for j := poss[len(words[i])+1]; j < len(words) && len(words[j]) == len(words[i])+1; j++ {
if isPredecessor(words[j], words[i]) {
dp[i] = max(dp[i], 1+dp[j])
}
}
res = max(res, dp[i])
}
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func isPredecessor(long, short string) bool {
i, j := 0, 0
wasMismatch := false
for j < len(short) {
if long[i] != short[j] {
if wasMismatch {
return false
}
wasMismatch = true
i++
continue
}
i++
j++
}
return true
}