Skip to content

Commit 27c748f

Browse files
authored
feat: add solutions to lc problem: No.0676 (doocs#2053)
No.0676.Implement Magic Dictionary
1 parent 751a9f0 commit 27c748f

File tree

8 files changed

+1058
-473
lines changed

8 files changed

+1058
-473
lines changed

solution/0600-0699/0676.Implement Magic Dictionary/README.md

Lines changed: 341 additions & 177 deletions
Large diffs are not rendered by default.

solution/0600-0699/0676.Implement Magic Dictionary/README_EN.md

Lines changed: 344 additions & 166 deletions
Large diffs are not rendered by default.
Lines changed: 71 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,72 @@
1-
class MagicDictionary {
2-
public:
3-
/** Initialize your data structure here. */
4-
MagicDictionary() {
5-
}
6-
7-
void buildDict(vector<string> dictionary) {
8-
for (string word : dictionary) {
9-
s.insert(word);
10-
for (string p : gen(word)) ++cnt[p];
11-
}
12-
}
13-
14-
bool search(string searchWord) {
15-
for (string p : gen(searchWord)) {
16-
if (cnt[p] > 1 || (cnt[p] == 1 && !s.count(searchWord))) return true;
17-
}
18-
return false;
19-
}
20-
21-
private:
22-
unordered_set<string> s;
23-
unordered_map<string, int> cnt;
24-
25-
vector<string> gen(string word) {
26-
vector<string> res;
27-
for (int i = 0; i < word.size(); ++i) {
28-
char c = word[i];
29-
word[i] = '*';
30-
res.push_back(word);
31-
word[i] = c;
32-
}
33-
return res;
34-
}
35-
};
36-
37-
/**
38-
* Your MagicDictionary object will be instantiated and called as such:
39-
* MagicDictionary* obj = new MagicDictionary();
40-
* obj->buildDict(dictionary);
41-
* bool param_2 = obj->search(searchWord);
1+
class Trie {
2+
private:
3+
Trie* children[26];
4+
bool isEnd = false;
5+
6+
public:
7+
Trie() {
8+
fill(begin(children), end(children), nullptr);
9+
}
10+
11+
void insert(const string& w) {
12+
Trie* node = this;
13+
for (char c : w) {
14+
int i = c - 'a';
15+
if (!node->children[i]) {
16+
node->children[i] = new Trie();
17+
}
18+
node = node->children[i];
19+
}
20+
node->isEnd = true;
21+
}
22+
23+
bool search(const string& w) {
24+
function<bool(int, Trie*, int)> dfs = [&](int i, Trie* node, int diff) {
25+
if (i >= w.size()) {
26+
return diff == 1 && node->isEnd;
27+
}
28+
int j = w[i] - 'a';
29+
if (node->children[j] && dfs(i + 1, node->children[j], diff)) {
30+
return true;
31+
}
32+
if (diff == 0) {
33+
for (int k = 0; k < 26; ++k) {
34+
if (k != j && node->children[k]) {
35+
if (dfs(i + 1, node->children[k], 1)) {
36+
return true;
37+
}
38+
}
39+
}
40+
}
41+
return false;
42+
};
43+
return dfs(0, this, 0);
44+
}
45+
};
46+
47+
class MagicDictionary {
48+
public:
49+
MagicDictionary() {
50+
trie = new Trie();
51+
}
52+
53+
void buildDict(vector<string> dictionary) {
54+
for (auto& w : dictionary) {
55+
trie->insert(w);
56+
}
57+
}
58+
59+
bool search(string searchWord) {
60+
return trie->search(searchWord);
61+
}
62+
63+
private:
64+
Trie* trie;
65+
};
66+
67+
/**
68+
* Your MagicDictionary object will be instantiated and called as such:
69+
* MagicDictionary* obj = new MagicDictionary();
70+
* obj->buildDict(dictionary);
71+
* bool param_2 = obj->search(searchWord);
4272
*/

solution/0600-0699/0676.Implement Magic Dictionary/Solution.go

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,62 @@
1-
type MagicDictionary struct {
2-
s map[string]bool
3-
cnt map[string]int
1+
type Trie struct {
2+
children [26]*Trie
3+
isEnd bool
44
}
55

6-
/** Initialize your data structure here. */
7-
func Constructor() MagicDictionary {
8-
return MagicDictionary{map[string]bool{}, map[string]int{}}
6+
func NewTrie() *Trie {
7+
return &Trie{}
98
}
109

11-
func (this *MagicDictionary) BuildDict(dictionary []string) {
12-
for _, word := range dictionary {
13-
this.s[word] = true
14-
for _, p := range gen(word) {
15-
this.cnt[p]++
10+
func (t *Trie) Insert(w string) {
11+
node := t
12+
for _, c := range w {
13+
i := c - 'a'
14+
if node.children[i] == nil {
15+
node.children[i] = NewTrie()
1616
}
17+
node = node.children[i]
1718
}
19+
node.isEnd = true
1820
}
1921

20-
func (this *MagicDictionary) Search(searchWord string) bool {
21-
for _, p := range gen(searchWord) {
22-
if this.cnt[p] > 1 || (this.cnt[p] == 1 && !this.s[searchWord]) {
22+
func (t *Trie) Search(w string) bool {
23+
var dfs func(int, *Trie, int) bool
24+
dfs = func(i int, node *Trie, diff int) bool {
25+
if i >= len(w) {
26+
return diff == 1 && node.isEnd
27+
}
28+
j := int(w[i] - 'a')
29+
if node.children[j] != nil && dfs(i+1, node.children[j], diff) {
2330
return true
2431
}
32+
if diff == 0 {
33+
for k := 0; k < 26; k++ {
34+
if k != j && node.children[k] != nil && dfs(i+1, node.children[k], 1) {
35+
return true
36+
}
37+
}
38+
}
39+
return false
2540
}
26-
return false
41+
return dfs(0, t, 0)
42+
}
43+
44+
type MagicDictionary struct {
45+
trie *Trie
46+
}
47+
48+
func Constructor() MagicDictionary {
49+
return MagicDictionary{trie: NewTrie()}
2750
}
2851

29-
func gen(word string) []string {
30-
var res []string
31-
for i := 0; i < len(word); i++ {
32-
res = append(res, word[:i]+"."+word[i+1:])
52+
func (md *MagicDictionary) BuildDict(dictionary []string) {
53+
for _, w := range dictionary {
54+
md.trie.Insert(w)
3355
}
34-
return res
56+
}
57+
58+
func (md *MagicDictionary) Search(searchWord string) bool {
59+
return md.trie.Search(searchWord)
3560
}
3661

3762
/**
Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,66 @@
1-
class MagicDictionary {
2-
private Set<String> s = new HashSet<>();
3-
private Map<String, Integer> cnt = new HashMap<>();
4-
5-
/** Initialize your data structure here. */
6-
public MagicDictionary() {
7-
}
8-
9-
public void buildDict(String[] dictionary) {
10-
for (String word : dictionary) {
11-
s.add(word);
12-
for (String p : gen(word)) {
13-
cnt.put(p, cnt.getOrDefault(p, 0) + 1);
14-
}
15-
}
16-
}
17-
18-
public boolean search(String searchWord) {
19-
for (String p : gen(searchWord)) {
20-
int v = cnt.getOrDefault(p, 0);
21-
if (v > 1 || (v == 1 && !s.contains(searchWord))) {
22-
return true;
23-
}
24-
}
25-
return false;
26-
}
27-
28-
private List<String> gen(String word) {
29-
List<String> res = new ArrayList<>();
30-
char[] chars = word.toCharArray();
31-
for (int i = 0; i < chars.length; ++i) {
32-
char c = chars[i];
33-
chars[i] = '*';
34-
res.add(new String(chars));
35-
chars[i] = c;
36-
}
37-
return res;
38-
}
39-
}
40-
41-
/**
42-
* Your MagicDictionary object will be instantiated and called as such:
43-
* MagicDictionary obj = new MagicDictionary();
44-
* obj.buildDict(dictionary);
45-
* boolean param_2 = obj.search(searchWord);
1+
class Trie {
2+
private Trie[] children = new Trie[26];
3+
private boolean isEnd;
4+
5+
public void insert(String w) {
6+
Trie node = this;
7+
for (char c : w.toCharArray()) {
8+
int i = c - 'a';
9+
if (node.children[i] == null) {
10+
node.children[i] = new Trie();
11+
}
12+
node = node.children[i];
13+
}
14+
node.isEnd = true;
15+
}
16+
17+
public boolean search(String w) {
18+
return dfs(w, 0, this, 0);
19+
}
20+
21+
private boolean dfs(String w, int i, Trie node, int diff) {
22+
if (i == w.length()) {
23+
return diff == 1 && node.isEnd;
24+
}
25+
int j = w.charAt(i) - 'a';
26+
if (node.children[j] != null) {
27+
if (dfs(w, i + 1, node.children[j], diff)) {
28+
return true;
29+
}
30+
}
31+
if (diff == 0) {
32+
for (int k = 0; k < 26; k++) {
33+
if (k != j && node.children[k] != null) {
34+
if (dfs(w, i + 1, node.children[k], 1)) {
35+
return true;
36+
}
37+
}
38+
}
39+
}
40+
return false;
41+
}
42+
}
43+
44+
class MagicDictionary {
45+
private Trie trie = new Trie();
46+
47+
public MagicDictionary() {
48+
}
49+
50+
public void buildDict(String[] dictionary) {
51+
for (String w : dictionary) {
52+
trie.insert(w);
53+
}
54+
}
55+
56+
public boolean search(String searchWord) {
57+
return trie.search(searchWord);
58+
}
59+
}
60+
61+
/**
62+
* Your MagicDictionary object will be instantiated and called as such:
63+
* MagicDictionary obj = new MagicDictionary();
64+
* obj.buildDict(dictionary);
65+
* boolean param_2 = obj.search(searchWord);
4666
*/
Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,44 @@
1-
class MagicDictionary:
2-
def __init__(self):
3-
"""
4-
Initialize your data structure here.
5-
"""
6-
7-
def gen(self, word):
8-
return [word[:i] + '*' + word[i + 1 :] for i in range(len(word))]
9-
10-
def buildDict(self, dictionary: List[str]) -> None:
11-
self.s = set(dictionary)
12-
self.cnt = Counter(p for word in dictionary for p in self.gen(word))
13-
14-
def search(self, searchWord: str) -> bool:
15-
for p in self.gen(searchWord):
16-
if self.cnt[p] > 1 or (self.cnt[p] == 1 and searchWord not in self.s):
17-
return True
18-
return False
19-
20-
21-
# Your MagicDictionary object will be instantiated and called as such:
22-
# obj = MagicDictionary()
23-
# obj.buildDict(dictionary)
24-
# param_2 = obj.search(searchWord)
1+
class Trie:
2+
__slots__ = ["children", "is_end"]
3+
4+
def __init__(self):
5+
self.children = {}
6+
self.is_end = False
7+
8+
def insert(self, w: str) -> None:
9+
node = self
10+
for c in w:
11+
if c not in node.children:
12+
node.children[c] = Trie()
13+
node = node.children[c]
14+
node.is_end = True
15+
16+
def search(self, w: str) -> bool:
17+
def dfs(i: int, node: Trie, diff: int) -> bool:
18+
if i == len(w):
19+
return diff == 1 and node.is_end
20+
if w[i] in node.children and dfs(i + 1, node.children[w[i]], diff):
21+
return True
22+
return diff == 0 and any(
23+
dfs(i + 1, node.children[c], 1) for c in node.children if c != w[i]
24+
)
25+
26+
return dfs(0, self, 0)
27+
28+
29+
class MagicDictionary:
30+
def __init__(self):
31+
self.trie = Trie()
32+
33+
def buildDict(self, dictionary: List[str]) -> None:
34+
for w in dictionary:
35+
self.trie.insert(w)
36+
37+
def search(self, searchWord: str) -> bool:
38+
return self.trie.search(searchWord)
39+
40+
41+
# Your MagicDictionary object will be instantiated and called as such:
42+
# obj = MagicDictionary()
43+
# obj.buildDict(dictionary)
44+
# param_2 = obj.search(searchWord)

0 commit comments

Comments
 (0)