Given an array of strings words
(without duplicates), return all the concatenated words in the given list of words
.
A concatenated word is defined as a string that is comprised entirely of at least two shorter words in the given array.
Example 1:
Input: words = ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"] Output: ["catsdogcats","dogcatsdog","ratcatdogcat"] Explanation: "catsdogcats" can be concatenated by "cats", "dog" and "cats"; "dogcatsdog" can be concatenated by "dog", "cats" and "dog"; "ratcatdogcat" can be concatenated by "rat", "cat", "dog" and "cat".
Example 2:
Input: words = ["cat","dog","catdog"] Output: ["catdog"]
Constraints:
1 <= words.length <= 104
0 <= words[i].length <= 30
words[i]
consists of only lowercase English letters.0 <= sum(words[i].length) <= 105
题目给定一个字符串数组words,数组中含有一系列长度不等的单词(无重复单词),要求找出所有可以由数组中更短的单词连接而成的单词。
一个单词肯定是由比它自身长度短的单词连接而成,显然对于数组words里单词,我们应该从短到长进行判断,因此首先应该对words里单词按长度进行排序,然后在从左到右判断依次当前单词是否可以由它前面的单词连接而成。
那么该如何判断一个单词是否能由一组更短的单词连接而成呢?这里可以使用动态规划来解,如果我们能知道单词的任意一个位置到单词开头部分是否由更短单词连接而成,那么单词最后一个位置到开头就是单词本身,从而也就知道该该单词能否由更短的单词连接而成。对于单词中的一个位置i,如果能找到它前面某个位置j之前是可连接单词,那么只要判断j和i之间构成的单词是否是数组words中的一个单词,如果是,那么从i到单词头构成的单词就是一个可连接词。由此可以看出,只要位置i之前的位置都判断过了,那么就可能快速判断第i位置。因此,我们可以按此方法从数组的第0位置到第n-1位置依次判断,判断完第n-1位置就可以知道答案。
class Solution:
def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:
def comp(w1, w2):
return len(w1) - len(w2)
words.sort(key=cmp_to_key(comp))
self.wset = set()
res =[]
for w in words:
if self.concatenated(w):
res.append(w)
self.wset.add(w)
return res
def concatenated(self, word: str)->bool:
n = len(word)
if n == 0:
return False
dp = [False] * (n + 1)
dp[0] = True
for i in range(1, n+1):
for j in range(i - 1, -1, -1):
if dp[j] and word[j:i] in self.wset:
dp[i] = True
break
return dp[n]