From c2c20e8072029efadc56874eda65d1d2dd64cffd Mon Sep 17 00:00:00 2001 From: yanglbme Date: Thu, 30 Nov 2023 20:15:50 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.1858 No.1858.Longest Word With All Prefixes --- .../README.md | 289 +++++++++++++---- .../README_EN.md | 291 ++++++++++++++---- .../Solution.cpp | 93 +++--- .../Solution.cs | 47 +++ .../Solution.go | 31 +- .../Solution.java | 95 +++--- .../Solution.py | 72 ++--- .../Solution.rs | 52 ++++ .../Solution.ts | 42 +++ 9 files changed, 749 insertions(+), 263 deletions(-) create mode 100644 solution/1800-1899/1858.Longest Word With All Prefixes/Solution.cs create mode 100644 solution/1800-1899/1858.Longest Word With All Prefixes/Solution.rs create mode 100644 solution/1800-1899/1858.Longest Word With All Prefixes/Solution.ts diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/README.md b/solution/1800-1899/1858.Longest Word With All Prefixes/README.md index 02955a9f769fe..285c4d782fe53 100644 --- a/solution/1800-1899/1858.Longest Word With All Prefixes/README.md +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/README.md @@ -53,6 +53,14 @@ **方法一:前缀树** +我们定义一棵前缀树,前缀树每个节点有两个属性,一个是长度为 $26$ 的子节点数组 `children`,另一个是是否为单词结尾的标记 `isEnd`。 + +我们遍历 `words`,对于每个单词 `w`,我们从根节点开始遍历,如果当前节点的子节点数组中没有 `w` 的第一个字符,我们就创建一个新的节点,然后继续遍历 `w` 的下一个字符,直到遍历完 `w`,我们将当前节点的 `isEnd` 标记为 `true`。 + +接下来我们遍历 `words`,对于每个单词 `w`,我们从根节点开始遍历,如果当前节点的子节点数组的 `isEnd` 字段为 `false`,说明 `w` 的某个前缀不在 `words` 中,我们返回 `false`。否则继续遍历 `w` 的下一个字符,直到遍历完 `w`,我们返回 `true`。 + +时间复杂度 $O(\sum_{w \in words} |w|)$,空间复杂度 $O(\sum_{w \in words} |w|)$。 + ### **Python3** @@ -61,20 +69,22 @@ ```python class Trie: + __slots__ = ["children", "is_end"] + def __init__(self): - self.children = [None] * 26 - self.is_end = False + self.children: List[Trie | None] = [None] * 26 + self.is_end: bool = False - def insert(self, w): + def insert(self, w: str) -> None: node = self for c in w: idx = ord(c) - ord("a") - if node.children[idx] is None: + if not node.children[idx]: node.children[idx] = Trie() node = node.children[idx] node.is_end = True - def search(self, w): + def search(self, w: str) -> bool: node = self for c in w: idx = ord(c) - ord("a") @@ -91,9 +101,7 @@ class Solution: trie.insert(w) ans = "" for w in words: - if ans and (len(ans) > len(w) or (len(ans) == len(w) and ans < w)): - continue - if trie.search(w): + if (len(w) > len(ans) or len(w) == len(ans) and w < ans) and trie.search(w): ans = w return ans ``` @@ -104,26 +112,29 @@ class Solution: ```java class Trie { - Trie[] children = new Trie[26]; - boolean isEnd; + private Trie[] children = new Trie[26]; + private boolean isEnd; + + public Trie() { + } - void insert(String w) { + public void insert(String w) { Trie node = this; for (char c : w.toCharArray()) { - c -= 'a'; - if (node.children[c] == null) { - node.children[c] = new Trie(); + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); } - node = node.children[c]; + node = node.children[idx]; } node.isEnd = true; } - boolean search(String w) { + public boolean search(String w) { Trie node = this; for (char c : w.toCharArray()) { - c -= 'a'; - node = node.children[c]; + int idx = c - 'a'; + node = node.children[idx]; if (!node.isEnd) { return false; } @@ -140,12 +151,8 @@ class Solution { } String ans = ""; for (String w : words) { - if (!"".equals(ans) - && (ans.length() > w.length() - || (ans.length() == w.length() && ans.compareTo(w) < 0))) { - continue; - } - if (trie.search(w)) { + if ((w.length() > ans.length() || (w.length() == ans.length() && w.compareTo(ans) < 0)) + && trie.search(w)) { ans = w; } } @@ -159,30 +166,34 @@ class Solution { ```cpp class Trie { private: - vector children; - bool isEnd; + Trie* children[26]; + bool isEnd = false; public: - Trie() - : children(26) - , isEnd(false) {} + Trie() { + fill(begin(children), end(children), nullptr); + } - void insert(string word) { + void insert(const string& w) { Trie* node = this; - for (char c : word) { - c -= 'a'; - if (!node->children[c]) node->children[c] = new Trie(); - node = node->children[c]; + for (char c : w) { + int idx = c - 'a'; + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } + node = node->children[idx]; } node->isEnd = true; } - bool search(string word) { + bool search(const string& w) { Trie* node = this; - for (char c : word) { - c -= 'a'; - node = node->children[c]; - if (!node->isEnd) return false; + for (char c : w) { + int idx = c - 'a'; + node = node->children[idx]; + if (!node->isEnd) { + return false; + } } return true; } @@ -191,12 +202,15 @@ public: class Solution { public: string longestWord(vector& words) { - Trie* trie = new Trie(); - for (auto w : words) trie->insert(w); + Trie trie; + for (const string& w : words) { + trie.insert(w); + } string ans = ""; - for (auto w : words) { - if (ans != "" && (ans.size() > w.size() || (ans.size() == w.size() && ans < w))) continue; - if (trie->search(w)) ans = w; + for (const string& w : words) { + if ((w.size() > ans.size() || (w.size() == ans.size() && w < ans)) && trie.search(w)) { + ans = w; + } } return ans; } @@ -214,22 +228,24 @@ type Trie struct { func newTrie() *Trie { return &Trie{} } -func (this *Trie) insert(word string) { - node := this - for _, c := range word { - c -= 'a' - if node.children[c] == nil { - node.children[c] = newTrie() + +func (t *Trie) insert(w string) { + node := t + for _, c := range w { + idx := c - 'a' + if node.children[idx] == nil { + node.children[idx] = newTrie() } - node = node.children[c] + node = node.children[idx] } node.isEnd = true } -func (this *Trie) search(word string) bool { - node := this - for _, c := range word { - c -= 'a' - node = node.children[c] + +func (t *Trie) search(w string) bool { + node := t + for _, c := range w { + idx := c - 'a' + node = node.children[idx] if !node.isEnd { return false } @@ -244,10 +260,7 @@ func longestWord(words []string) string { } ans := "" for _, w := range words { - if ans != "" && (len(ans) > len(w) || (len(ans) == len(w) && ans < w)) { - continue - } - if trie.search(w) { + if (len(w) > len(ans) || (len(w) == len(ans) && w < ans)) && trie.search(w) { ans = w } } @@ -255,6 +268,162 @@ func longestWord(words []string) string { } ``` +### **TypeScript** + +```ts +class Trie { + private children: (Trie | null)[] = Array(26).fill(null); + private isEnd: boolean = false; + + insert(w: string): void { + let node: Trie = this; + for (const c of w) { + const idx: number = c.charCodeAt(0) - 'a'.charCodeAt(0); + if (!node.children[idx]) { + node.children[idx] = new Trie(); + } + node = node.children[idx] as Trie; + } + node.isEnd = true; + } + + search(w: string): boolean { + let node: Trie = this; + for (const c of w) { + const idx: number = c.charCodeAt(0) - 'a'.charCodeAt(0); + node = node.children[idx] as Trie; + if (!node.isEnd) { + return false; + } + } + return true; + } +} + +function longestWord(words: string[]): string { + const trie: Trie = new Trie(); + for (const w of words) { + trie.insert(w); + } + let ans: string = ''; + for (const w of words) { + if ((w.length > ans.length || (w.length === ans.length && w < ans)) && trie.search(w)) { + ans = w; + } + } + return ans; +} +``` + +### **Rust** + +```rust +struct Trie { + children: [Option>; 26], + is_end: bool, +} + +impl Trie { + fn new() -> Self { + Trie { + children: Default::default(), + is_end: false, + } + } + + fn insert(&mut self, w: &str) { + let mut node = self; + for c in w.chars() { + let idx = (c as usize) - ('a' as usize); + node = node.children[idx].get_or_insert_with(|| Box::new(Trie::new())); + } + node.is_end = true; + } + + fn search(&self, w: &str) -> bool { + let mut node = self; + for c in w.chars() { + let idx = (c as usize) - ('a' as usize); + if let Some(next_node) = &node.children[idx] { + node = next_node.as_ref(); + if !node.is_end { + return false; + } + } + } + true + } +} + +impl Solution { + pub fn longest_word(words: Vec) -> String { + let mut trie = Trie::new(); + for w in &words { + trie.insert(w); + } + let mut ans = String::new(); + for w in &words { + if (w.len() > ans.len() || (w.len() == ans.len() && w < &ans)) && trie.search(w) { + ans = w.clone(); + } + } + ans + } +} +``` + +### **C#** + +```cs +public class Trie { + private Trie[] children = new Trie[26]; + private bool isEnd; + + public Trie() { } + + public void Insert(string w) { + Trie node = this; + foreach (char c in w.ToCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + } + node.isEnd = true; + } + + public bool Search(string w) { + Trie node = this; + foreach (char c in w.ToCharArray()) { + int idx = c - 'a'; + node = node.children[idx]; + if (!node.isEnd) { + return false; + } + } + return true; + } +} + +public class Solution { + public string LongestWord(string[] words) { + Trie trie = new Trie(); + foreach (string w in words) { + trie.Insert(w); + } + + string ans = ""; + foreach (string w in words) { + if ((w.Length > ans.Length || (w.Length == ans.Length && string.Compare(w, ans) < 0)) && trie.Search(w)) { + ans = w; + } + } + return ans; + } +} +``` + ### **...** ``` diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/README_EN.md b/solution/1800-1899/1858.Longest Word With All Prefixes/README_EN.md index 2f32e3a04d40b..9e1a15022f8cf 100644 --- a/solution/1800-1899/1858.Longest Word With All Prefixes/README_EN.md +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/README_EN.md @@ -48,26 +48,38 @@ However, "apple" is lexicographically smaller, so we return that. ## Solutions +**Solution 1: Trie** + +We define a trie, each node of the trie has two attributes, one is a `children` array of length $26$, and the other is a `isEnd` flag indicating whether it is the end of a word. + +We traverse `words`, for each word `w`, we start traversing from the root node. If the current node's `children` array does not contain the first character of `w`, we create a new node, then continue to traverse the next character of `w`, until we finish traversing `w`, we mark the `isEnd` of the current node as `true`. + +Next, we traverse `words`, for each word `w`, we start traversing from the root node. If the `isEnd` field of the current node's `children` array is `false`, it means that some prefix of `w` is not in `words`, we return `false`. Otherwise, we continue to traverse the next character of `w`, until we finish traversing `w`, we return `true`. + +The time complexity is $O(\sum_{w \in words} |w|)$, and the space complexity is $O(\sum_{w \in words} |w|)$. + ### **Python3** ```python class Trie: + __slots__ = ["children", "is_end"] + def __init__(self): - self.children = [None] * 26 - self.is_end = False + self.children: List[Trie | None] = [None] * 26 + self.is_end: bool = False - def insert(self, w): + def insert(self, w: str) -> None: node = self for c in w: idx = ord(c) - ord("a") - if node.children[idx] is None: + if not node.children[idx]: node.children[idx] = Trie() node = node.children[idx] node.is_end = True - def search(self, w): + def search(self, w: str) -> bool: node = self for c in w: idx = ord(c) - ord("a") @@ -84,9 +96,7 @@ class Solution: trie.insert(w) ans = "" for w in words: - if ans and (len(ans) > len(w) or (len(ans) == len(w) and ans < w)): - continue - if trie.search(w): + if (len(w) > len(ans) or len(w) == len(ans) and w < ans) and trie.search(w): ans = w return ans ``` @@ -95,26 +105,29 @@ class Solution: ```java class Trie { - Trie[] children = new Trie[26]; - boolean isEnd; + private Trie[] children = new Trie[26]; + private boolean isEnd; - void insert(String w) { + public Trie() { + } + + public void insert(String w) { Trie node = this; for (char c : w.toCharArray()) { - c -= 'a'; - if (node.children[c] == null) { - node.children[c] = new Trie(); + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); } - node = node.children[c]; + node = node.children[idx]; } node.isEnd = true; } - boolean search(String w) { + public boolean search(String w) { Trie node = this; for (char c : w.toCharArray()) { - c -= 'a'; - node = node.children[c]; + int idx = c - 'a'; + node = node.children[idx]; if (!node.isEnd) { return false; } @@ -131,12 +144,8 @@ class Solution { } String ans = ""; for (String w : words) { - if (!"".equals(ans) - && (ans.length() > w.length() - || (ans.length() == w.length() && ans.compareTo(w) < 0))) { - continue; - } - if (trie.search(w)) { + if ((w.length() > ans.length() || (w.length() == ans.length() && w.compareTo(ans) < 0)) + && trie.search(w)) { ans = w; } } @@ -150,30 +159,34 @@ class Solution { ```cpp class Trie { private: - vector children; - bool isEnd; + Trie* children[26]; + bool isEnd = false; public: - Trie() - : children(26) - , isEnd(false) {} + Trie() { + fill(begin(children), end(children), nullptr); + } - void insert(string word) { + void insert(const string& w) { Trie* node = this; - for (char c : word) { - c -= 'a'; - if (!node->children[c]) node->children[c] = new Trie(); - node = node->children[c]; + for (char c : w) { + int idx = c - 'a'; + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } + node = node->children[idx]; } node->isEnd = true; } - bool search(string word) { + bool search(const string& w) { Trie* node = this; - for (char c : word) { - c -= 'a'; - node = node->children[c]; - if (!node->isEnd) return false; + for (char c : w) { + int idx = c - 'a'; + node = node->children[idx]; + if (!node->isEnd) { + return false; + } } return true; } @@ -182,12 +195,15 @@ public: class Solution { public: string longestWord(vector& words) { - Trie* trie = new Trie(); - for (auto w : words) trie->insert(w); + Trie trie; + for (const string& w : words) { + trie.insert(w); + } string ans = ""; - for (auto w : words) { - if (ans != "" && (ans.size() > w.size() || (ans.size() == w.size() && ans < w))) continue; - if (trie->search(w)) ans = w; + for (const string& w : words) { + if ((w.size() > ans.size() || (w.size() == ans.size() && w < ans)) && trie.search(w)) { + ans = w; + } } return ans; } @@ -205,22 +221,24 @@ type Trie struct { func newTrie() *Trie { return &Trie{} } -func (this *Trie) insert(word string) { - node := this - for _, c := range word { - c -= 'a' - if node.children[c] == nil { - node.children[c] = newTrie() + +func (t *Trie) insert(w string) { + node := t + for _, c := range w { + idx := c - 'a' + if node.children[idx] == nil { + node.children[idx] = newTrie() } - node = node.children[c] + node = node.children[idx] } node.isEnd = true } -func (this *Trie) search(word string) bool { - node := this - for _, c := range word { - c -= 'a' - node = node.children[c] + +func (t *Trie) search(w string) bool { + node := t + for _, c := range w { + idx := c - 'a' + node = node.children[idx] if !node.isEnd { return false } @@ -235,10 +253,7 @@ func longestWord(words []string) string { } ans := "" for _, w := range words { - if ans != "" && (len(ans) > len(w) || (len(ans) == len(w) && ans < w)) { - continue - } - if trie.search(w) { + if (len(w) > len(ans) || (len(w) == len(ans) && w < ans)) && trie.search(w) { ans = w } } @@ -246,6 +261,162 @@ func longestWord(words []string) string { } ``` +### **TypeScript** + +```ts +class Trie { + private children: (Trie | null)[] = Array(26).fill(null); + private isEnd: boolean = false; + + insert(w: string): void { + let node: Trie = this; + for (const c of w) { + const idx: number = c.charCodeAt(0) - 'a'.charCodeAt(0); + if (!node.children[idx]) { + node.children[idx] = new Trie(); + } + node = node.children[idx] as Trie; + } + node.isEnd = true; + } + + search(w: string): boolean { + let node: Trie = this; + for (const c of w) { + const idx: number = c.charCodeAt(0) - 'a'.charCodeAt(0); + node = node.children[idx] as Trie; + if (!node.isEnd) { + return false; + } + } + return true; + } +} + +function longestWord(words: string[]): string { + const trie: Trie = new Trie(); + for (const w of words) { + trie.insert(w); + } + let ans: string = ''; + for (const w of words) { + if ((w.length > ans.length || (w.length === ans.length && w < ans)) && trie.search(w)) { + ans = w; + } + } + return ans; +} +``` + +### **Rust** + +```rust +struct Trie { + children: [Option>; 26], + is_end: bool, +} + +impl Trie { + fn new() -> Self { + Trie { + children: Default::default(), + is_end: false, + } + } + + fn insert(&mut self, w: &str) { + let mut node = self; + for c in w.chars() { + let idx = (c as usize) - ('a' as usize); + node = node.children[idx].get_or_insert_with(|| Box::new(Trie::new())); + } + node.is_end = true; + } + + fn search(&self, w: &str) -> bool { + let mut node = self; + for c in w.chars() { + let idx = (c as usize) - ('a' as usize); + if let Some(next_node) = &node.children[idx] { + node = next_node.as_ref(); + if !node.is_end { + return false; + } + } + } + true + } +} + +impl Solution { + pub fn longest_word(words: Vec) -> String { + let mut trie = Trie::new(); + for w in &words { + trie.insert(w); + } + let mut ans = String::new(); + for w in &words { + if (w.len() > ans.len() || (w.len() == ans.len() && w < &ans)) && trie.search(w) { + ans = w.clone(); + } + } + ans + } +} +``` + +### **C#** + +```cs +public class Trie { + private Trie[] children = new Trie[26]; + private bool isEnd; + + public Trie() { } + + public void Insert(string w) { + Trie node = this; + foreach (char c in w.ToCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + } + node.isEnd = true; + } + + public bool Search(string w) { + Trie node = this; + foreach (char c in w.ToCharArray()) { + int idx = c - 'a'; + node = node.children[idx]; + if (!node.isEnd) { + return false; + } + } + return true; + } +} + +public class Solution { + public string LongestWord(string[] words) { + Trie trie = new Trie(); + foreach (string w in words) { + trie.Insert(w); + } + + string ans = ""; + foreach (string w in words) { + if ((w.Length > ans.Length || (w.Length == ans.Length && string.Compare(w, ans) < 0)) && trie.Search(w)) { + ans = w; + } + } + return ans; + } +} +``` + ### **...** ``` diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.cpp b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.cpp index f02d839f2591e..db89304be2c06 100644 --- a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.cpp +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.cpp @@ -1,44 +1,51 @@ -class Trie { -private: - vector children; - bool isEnd; - -public: - Trie() - : children(26) - , isEnd(false) {} - - void insert(string word) { - Trie* node = this; - for (char c : word) { - c -= 'a'; - if (!node->children[c]) node->children[c] = new Trie(); - node = node->children[c]; - } - node->isEnd = true; - } - - bool search(string word) { - Trie* node = this; - for (char c : word) { - c -= 'a'; - node = node->children[c]; - if (!node->isEnd) return false; - } - return true; - } -}; - -class Solution { -public: - string longestWord(vector& words) { - Trie* trie = new Trie(); - for (auto w : words) trie->insert(w); - string ans = ""; - for (auto w : words) { - if (ans != "" && (ans.size() > w.size() || (ans.size() == w.size() && ans < w))) continue; - if (trie->search(w)) ans = w; - } - return ans; - } +class Trie { +private: + Trie* children[26]; + bool isEnd = false; + +public: + Trie() { + fill(begin(children), end(children), nullptr); + } + + void insert(const string& w) { + Trie* node = this; + for (char c : w) { + int idx = c - 'a'; + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } + node = node->children[idx]; + } + node->isEnd = true; + } + + bool search(const string& w) { + Trie* node = this; + for (char c : w) { + int idx = c - 'a'; + node = node->children[idx]; + if (!node->isEnd) { + return false; + } + } + return true; + } +}; + +class Solution { +public: + string longestWord(vector& words) { + Trie trie; + for (const string& w : words) { + trie.insert(w); + } + string ans = ""; + for (const string& w : words) { + if ((w.size() > ans.size() || (w.size() == ans.size() && w < ans)) && trie.search(w)) { + ans = w; + } + } + return ans; + } }; \ No newline at end of file diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.cs b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.cs new file mode 100644 index 0000000000000..2bb78ce9d49ed --- /dev/null +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.cs @@ -0,0 +1,47 @@ +public class Trie { + private Trie[] children = new Trie[26]; + private bool isEnd; + + public Trie() { } + + public void Insert(string w) { + Trie node = this; + foreach (char c in w.ToCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + } + node.isEnd = true; + } + + public bool Search(string w) { + Trie node = this; + foreach (char c in w.ToCharArray()) { + int idx = c - 'a'; + node = node.children[idx]; + if (!node.isEnd) { + return false; + } + } + return true; + } +} + +public class Solution { + public string LongestWord(string[] words) { + Trie trie = new Trie(); + foreach (string w in words) { + trie.Insert(w); + } + + string ans = ""; + foreach (string w in words) { + if ((w.Length > ans.Length || (w.Length == ans.Length && string.Compare(w, ans) < 0)) && trie.Search(w)) { + ans = w; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.go b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.go index 1d68bcc101748..b666747efdbbf 100644 --- a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.go +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.go @@ -6,22 +6,24 @@ type Trie struct { func newTrie() *Trie { return &Trie{} } -func (this *Trie) insert(word string) { - node := this - for _, c := range word { - c -= 'a' - if node.children[c] == nil { - node.children[c] = newTrie() + +func (t *Trie) insert(w string) { + node := t + for _, c := range w { + idx := c - 'a' + if node.children[idx] == nil { + node.children[idx] = newTrie() } - node = node.children[c] + node = node.children[idx] } node.isEnd = true } -func (this *Trie) search(word string) bool { - node := this - for _, c := range word { - c -= 'a' - node = node.children[c] + +func (t *Trie) search(w string) bool { + node := t + for _, c := range w { + idx := c - 'a' + node = node.children[idx] if !node.isEnd { return false } @@ -36,10 +38,7 @@ func longestWord(words []string) string { } ans := "" for _, w := range words { - if ans != "" && (len(ans) > len(w) || (len(ans) == len(w) && ans < w)) { - continue - } - if trie.search(w) { + if (len(w) > len(ans) || (len(w) == len(ans) && w < ans)) && trie.search(w) { ans = w } } diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.java b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.java index 3b70fa1e5e695..f4f145597e88c 100644 --- a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.java +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.java @@ -1,49 +1,48 @@ -class Trie { - Trie[] children = new Trie[26]; - boolean isEnd; - - void insert(String w) { - Trie node = this; - for (char c : w.toCharArray()) { - c -= 'a'; - if (node.children[c] == null) { - node.children[c] = new Trie(); - } - node = node.children[c]; - } - node.isEnd = true; - } - - boolean search(String w) { - Trie node = this; - for (char c : w.toCharArray()) { - c -= 'a'; - node = node.children[c]; - if (!node.isEnd) { - return false; - } - } - return true; - } -} - -class Solution { - public String longestWord(String[] words) { - Trie trie = new Trie(); - for (String w : words) { - trie.insert(w); - } - String ans = ""; - for (String w : words) { - if (!"".equals(ans) - && (ans.length() > w.length() - || (ans.length() == w.length() && ans.compareTo(w) < 0))) { - continue; - } - if (trie.search(w)) { - ans = w; - } - } - return ans; - } +class Trie { + private Trie[] children = new Trie[26]; + private boolean isEnd; + + public Trie() { + } + + public void insert(String w) { + Trie node = this; + for (char c : w.toCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + } + node.isEnd = true; + } + + public boolean search(String w) { + Trie node = this; + for (char c : w.toCharArray()) { + int idx = c - 'a'; + node = node.children[idx]; + if (!node.isEnd) { + return false; + } + } + return true; + } +} + +class Solution { + public String longestWord(String[] words) { + Trie trie = new Trie(); + for (String w : words) { + trie.insert(w); + } + String ans = ""; + for (String w : words) { + if ((w.length() > ans.length() || (w.length() == ans.length() && w.compareTo(ans) < 0)) + && trie.search(w)) { + ans = w; + } + } + return ans; + } } \ No newline at end of file diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.py b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.py index 458fa26f7cb2b..0c542511f8692 100644 --- a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.py +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.py @@ -1,36 +1,36 @@ -class Trie: - def __init__(self): - self.children = [None] * 26 - self.is_end = False - - def insert(self, w): - node = self - for c in w: - idx = ord(c) - ord("a") - if node.children[idx] is None: - node.children[idx] = Trie() - node = node.children[idx] - node.is_end = True - - def search(self, w): - node = self - for c in w: - idx = ord(c) - ord("a") - node = node.children[idx] - if not node.is_end: - return False - return True - - -class Solution: - def longestWord(self, words: List[str]) -> str: - trie = Trie() - for w in words: - trie.insert(w) - ans = "" - for w in words: - if ans and (len(ans) > len(w) or (len(ans) == len(w) and ans < w)): - continue - if trie.search(w): - ans = w - return ans +class Trie: + __slots__ = ["children", "is_end"] + + def __init__(self): + self.children: List[Trie | None] = [None] * 26 + self.is_end: bool = False + + def insert(self, w: str) -> None: + node = self + for c in w: + idx = ord(c) - ord("a") + if not node.children[idx]: + node.children[idx] = Trie() + node = node.children[idx] + node.is_end = True + + def search(self, w: str) -> bool: + node = self + for c in w: + idx = ord(c) - ord("a") + node = node.children[idx] + if not node.is_end: + return False + return True + + +class Solution: + def longestWord(self, words: List[str]) -> str: + trie = Trie() + for w in words: + trie.insert(w) + ans = "" + for w in words: + if (len(w) > len(ans) or len(w) == len(ans) and w < ans) and trie.search(w): + ans = w + return ans diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.rs b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.rs new file mode 100644 index 0000000000000..6d10199a64ed3 --- /dev/null +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.rs @@ -0,0 +1,52 @@ +struct Trie { + children: [Option>; 26], + is_end: bool, +} + +impl Trie { + fn new() -> Self { + Trie { + children: Default::default(), + is_end: false, + } + } + + fn insert(&mut self, w: &str) { + let mut node = self; + for c in w.chars() { + let idx = (c as usize) - ('a' as usize); + node = node.children[idx].get_or_insert_with(|| Box::new(Trie::new())); + } + node.is_end = true; + } + + fn search(&self, w: &str) -> bool { + let mut node = self; + for c in w.chars() { + let idx = (c as usize) - ('a' as usize); + if let Some(next_node) = &node.children[idx] { + node = next_node.as_ref(); + if !node.is_end { + return false; + } + } + } + true + } +} + +impl Solution { + pub fn longest_word(words: Vec) -> String { + let mut trie = Trie::new(); + for w in &words { + trie.insert(w); + } + let mut ans = String::new(); + for w in &words { + if (w.len() > ans.len() || (w.len() == ans.len() && w < &ans)) && trie.search(w) { + ans = w.clone(); + } + } + ans + } +} diff --git a/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.ts b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.ts new file mode 100644 index 0000000000000..1f3b737f1d492 --- /dev/null +++ b/solution/1800-1899/1858.Longest Word With All Prefixes/Solution.ts @@ -0,0 +1,42 @@ +class Trie { + private children: (Trie | null)[] = Array(26).fill(null); + private isEnd: boolean = false; + + insert(w: string): void { + let node: Trie = this; + for (const c of w) { + const idx: number = c.charCodeAt(0) - 'a'.charCodeAt(0); + if (!node.children[idx]) { + node.children[idx] = new Trie(); + } + node = node.children[idx] as Trie; + } + node.isEnd = true; + } + + search(w: string): boolean { + let node: Trie = this; + for (const c of w) { + const idx: number = c.charCodeAt(0) - 'a'.charCodeAt(0); + node = node.children[idx] as Trie; + if (!node.isEnd) { + return false; + } + } + return true; + } +} + +function longestWord(words: string[]): string { + const trie: Trie = new Trie(); + for (const w of words) { + trie.insert(w); + } + let ans: string = ''; + for (const w of words) { + if ((w.length > ans.length || (w.length === ans.length && w < ans)) && trie.search(w)) { + ans = w; + } + } + return ans; +}