Skip to content

feat: add solutions to lc problem: No.1858 #2043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 229 additions & 60 deletions solution/1800-1899/1858.Longest Word With All Prefixes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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|)$。

<!-- tabs:start -->

### **Python3**
Expand All @@ -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")
Expand All @@ -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
```
Expand All @@ -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;
}
Expand All @@ -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;
}
}
Expand All @@ -159,30 +166,34 @@ class Solution {
```cpp
class Trie {
private:
vector<Trie*> 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;
}
Expand All @@ -191,12 +202,15 @@ public:
class Solution {
public:
string longestWord(vector<string>& 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;
}
Expand All @@ -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
}
Expand All @@ -244,17 +260,170 @@ 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
}
}
return ans
}
```

### **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<Box<Trie>>; 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>) -> 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;
}
}
```

### **...**

```
Expand Down
Loading