-
Notifications
You must be signed in to change notification settings - Fork 53
/
Copy path0472. Concatenated Words.js
67 lines (61 loc) · 2.21 KB
/
0472. Concatenated Words.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Given a list of words (without duplicates), please write a program that returns all 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:
// Input: ["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".
//
// Note:
// The number of elements of the given array will not exceed 10,000
// The length sum of elements in the given array will not exceed 600,000.
// All the input string will only include lower case letters.
// The returned elements order does not matter.
/**
* @param {string[]} words
* @return {string[]}
*/
// Reuse any O(n^2) solution in 139. Word Break
// Similar
// 139. Word Break
// 472. Concatenated Words
//
// Time O(N * L^2) where L is the word length
//
// This problem is just one more step further for the question 139. Word Break.
// We iterate through each word and see if it can be formed by using other words.
// A word can only be formed by words shorter than it. So we need first sort the input by length of each word,
// and only try to form one word by using words in front of it.
//
// Note it need modify 139. Word Break a little bit, instead of passing array and create set each time,
// need pass set directly to save time.
const findAllConcatenatedWordsInADict = (words) => {
const res = [];
const set = new Set();
words.sort((w1, w2) => w1.length - w2.length);
for (const w of words) {
if (wordBreak(w, set)) {
res.push(w);
}
set.add(w);
}
return res;
};
const wordBreak = (s, dict) => {
if (dict.size === 0) return false;
const dp = Array(s.length + 1).fill(false);
dp[0] = true;
for (let end = 1; end <= s.length; end++) {
for (let start = 0; start < end; start++) {
const w = s.slice(start, end);
if (dp[start] === true && dict.has(w)) {
dp[end] = true;
break;
}
}
}
return dp[s.length];
};