-
Notifications
You must be signed in to change notification settings - Fork 155
/
Copy pathconcatenated-words.js
105 lines (84 loc) · 2.26 KB
/
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**
* Concatenated Words
*
* 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.
*/
class TrieNode {
constructor() {
this.children = {};
this.word = null;
}
}
class Trie {
constructor(words) {
this.root = new TrieNode();
words.forEach(word => {
this.insert(word);
});
}
insert(word) {
if (!word) {
return;
}
let current = this.root;
for (let i = 0; i < word.length; i++) {
const c = word[i];
if (!current.children[c]) {
current.children[c] = new TrieNode();
}
current = current.children[c];
}
current.word = word;
}
search(word) {
let current = this.root;
for (let i = 0; i < word.length; i++) {
const c = word[i];
if (!current.children[c]) {
return 0;
}
current = current.children[c];
if (current.word) {
const rest = word.substr(current.word.length);
if (this.search(rest) > 0) {
return 2;
}
}
}
return current.word === word ? 1 : 0;
}
}
/**
* @param {string[]} words
* @return {string[]}
*/
const findAllConcatenatedWordsInADict = words => {
const results = [];
const trie = new Trie(words);
for (let i = 0; i < words.length; i++) {
const word = words[i];
const count = trie.search(word);
if (count > 1) {
results.push(word);
}
}
return results;
};
export default findAllConcatenatedWordsInADict;