[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 }

 

相关题目

140. Word Break II

472. Concatenated Words

LeetCode 题目总结

posted @ 2023-01-27 14:58  CNoodle  阅读(36)  评论(0编辑  收藏  举报