[LeetCode] 472. Concatenated Words
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
1 <= words[i].length <= 30
words[i]
consists of only lowercase English letters.- All the strings of
words
are unique. 1 <= sum(words[i].length) <= 105
连接词。
给你一个 不含重复 单词的字符串数组 words ,请你找出并返回 words 中的所有 连接词 。
连接词 定义为:一个完全由给定数组中的至少两个较短单词组成的字符串。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/concatenated-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题我提供一个动态规划的思路,我参考了这个帖子。
这道题跟140 word break ii很像,不过这道题是给你一个字符串数组,问你里面有哪些单词是可以被数组里其他更短的单词组成的。所以我们需要检查每个单词,看看有哪些单词是可以被数组中的其他单词所分解的。
判断一个单词是否可以被分解,我们需要一个 hashset,把所有单词装进去,这样当我们找到一个潜在的前缀的时候,我们就可以以 O(1) 的时间判断这个前缀是否存在于字符串数组。我们还需要一个 boolean 类型的 dp 数组,这个 dp[i] 数组的定义是当前这个单词的前缀 s.substring(0, i) 是可以被分割的。如果前缀是可以被分割的,那么我们只需要 O(1) 的时间,就可以判断当前这个单词的后缀是否也存在。
时间O(n^2 * m^2) - n 是单词的最大长度,m 是单词的个数
空间O(max(m, n))
Java实现
1 class Solution { 2 public List<String> findAllConcatenatedWordsInADict(String[] words) { 3 List<String> res = new ArrayList<>(); 4 HashSet<String> set = new HashSet<>(); 5 for (String w : words) { 6 set.add(w); 7 } 8 9 for (String word : words) { 10 set.remove(word); 11 if (canBreak(word, set)) { 12 res.add(word); 13 } 14 set.add(word); 15 } 16 return res; 17 } 18 19 private boolean canBreak(String s, HashSet<String> set) { 20 if (set.size() == 0) { 21 return false; 22 } 23 int n = s.length(); 24 if (n == 0) { 25 return false; 26 } 27 boolean[] dp = new boolean[n + 1]; 28 dp[0] = true; 29 for (int i = 1; i <= n; i++) { 30 for (int j = 0; j < i; j++) { 31 if (!dp[j]) { 32 continue; 33 } 34 if (set.contains(s.substring(j, i))) { 35 dp[i] = true; 36 break; 37 } 38 } 39 } 40 return dp[n]; 41 } 42 }
相关题目