From 6a8d3d2e87f7588096bb8444b1d81cbe1b42431e Mon Sep 17 00:00:00 2001 From: yanglbme Date: Fri, 2 Aug 2024 09:16:40 +0800 Subject: [PATCH 1/2] feat: update solutions to lc problem: No.2416 No.2416.Sum of Prefix Scores of Strings --- .../README.md | 76 +++++++------------ .../README_EN.md | 76 +++++++------------ .../Solution.cpp | 18 ++--- .../Solution.py | 6 +- .../Solution.ts | 56 ++++++++++---- .../Solution2.ts | 47 ------------ 6 files changed, 106 insertions(+), 173 deletions(-) delete mode 100644 solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution2.ts diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md index 68056afc595f9..77866649f6b80 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md @@ -47,7 +47,7 @@ tags: - 2 个字符串的前缀为 "a" ,2 个字符串的前缀为 "ab" 。 总计 answer[1] = 2 + 2 = 4 。 - "bc" 有 2 个前缀:"b" 和 "bc" 。 -- 2 个字符串的前缀为 "b" ,1 个字符串的前缀为 "bc" 。 +- 2 个字符串的前缀为 "b" ,1 个字符串的前缀为 "bc" 。 总计 answer[2] = 2 + 1 = 3 。 - "b" 有 1 个前缀:"b"。 - 2 个字符串的前缀为 "b" 。 @@ -81,11 +81,21 @@ tags: ### 方法一:前缀树 -用前缀树维护所有字符串的前缀以及每个前缀出现的次数。 +我们可以用前缀树来维护所有字符串的前缀以及每个前缀出现的次数。 -然后遍历每个字符串,累加每个前缀的出现次数即可。 +定义前缀树节点结构体 `Trie`,包含两个属性: -时间复杂度 $O(n \times m)$。其中 $n$, $m$ 分别为字符串数组 `words` 的长度和其中字符串的最大长度。 +- `children`:长度为 26 的数组,用于存储当前节点的子节点。 +- `cnt`:当前节点的出现次数。 + +定义前缀树的两个方法: + +- `insert`:插入一个字符串,将其前缀插入前缀树。 +- `search`:搜索一个字符串,返回其前缀的出现次数。 + +我们遍历所有字符串,将每个字符串插入前缀树中。然后再遍历所有字符串,对每个字符串调用 `search` 方法,累加每个前缀的出现次数即可。 + +时间复杂度 $O(L)$,空间复杂度 $O(L)$,其中 $L$ 是所有字符串的总长度。 @@ -93,6 +103,8 @@ tags: ```python class Trie: + __slots__ = "children", "cnt" + def __init__(self): self.children = [None] * 26 self.cnt = 0 @@ -100,7 +112,7 @@ class Trie: def insert(self, w): node = self for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] @@ -110,7 +122,7 @@ class Trie: node = self ans = 0 for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: return ans node = node.children[idx] @@ -180,19 +192,17 @@ class Solution { ```cpp class Trie { private: - vector children; - int cnt; + Trie* children[26]{}; + int cnt = 0; public: - Trie() - : children(26) - , cnt(0) {} - void insert(string& w) { Trie* node = this; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) node->children[idx] = new Trie(); + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } node = node->children[idx]; ++node->cnt; } @@ -203,7 +213,9 @@ public: int ans = 0; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) return ans; + if (!node->children[idx]) { + return ans; + } node = node->children[idx]; ans += node->cnt; } @@ -279,42 +291,6 @@ func sumPrefixScores(words []string) []int { #### TypeScript -```ts -function sumPrefixScores(words: string[]): number[] { - const map = new Map(); - - for (const word of words) { - const n = word.length; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - map.set(s, (map.get(s) ?? 0) + 1); - } - } - - return words.map(word => { - const n = word.length; - let count = 0; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - count += map.get(s); - } - return count; - }); -} -``` - - - - - - - -### 方法二 - - - -#### TypeScript - ```ts class Trie { children: Array; diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md index 683e263314376..649cb15bc5949 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md @@ -79,13 +79,23 @@ Each prefix has a score of one, so the total is answer[0] = 1 + 1 + 1 + 1 = 4. -### Solution 1: Trie +### Solution 1: Prefix Tree -Use a trie to maintain the prefixes of all strings and the occurrence count of each prefix. +We can use a prefix tree to maintain all prefixes of the strings and count the occurrences of each prefix. -Then, traverse each string, accumulating the occurrence count of each prefix. +Define the prefix tree node structure `Trie`, which includes two properties: -The time complexity is $O(n \times m)$. Here, $n$ and $m$ are the length of the string array `words` and the maximum length of the strings in it, respectively. +- `children`: An array of length 26 used to store the current node's children. +- `cnt`: The occurrence count of the current node. + +Define two methods for the prefix tree: + +- `insert`: Inserts a string, adding its prefixes into the prefix tree. +- `search`: Searches for a string and returns the occurrence count of its prefixes. + +We traverse all strings, inserting each string into the prefix tree. Then we traverse all strings again, calling the `search` method for each string and summing up the occurrence counts of each prefix. + +Time complexity is $O(L)$, and space complexity is $O(L)$, where $L$ is the total length of all strings. @@ -93,6 +103,8 @@ The time complexity is $O(n \times m)$. Here, $n$ and $m$ are the length of the ```python class Trie: + __slots__ = "children", "cnt" + def __init__(self): self.children = [None] * 26 self.cnt = 0 @@ -100,7 +112,7 @@ class Trie: def insert(self, w): node = self for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] @@ -110,7 +122,7 @@ class Trie: node = self ans = 0 for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: return ans node = node.children[idx] @@ -180,19 +192,17 @@ class Solution { ```cpp class Trie { private: - vector children; - int cnt; + Trie* children[26]{}; + int cnt = 0; public: - Trie() - : children(26) - , cnt(0) {} - void insert(string& w) { Trie* node = this; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) node->children[idx] = new Trie(); + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } node = node->children[idx]; ++node->cnt; } @@ -203,7 +213,9 @@ public: int ans = 0; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) return ans; + if (!node->children[idx]) { + return ans; + } node = node->children[idx]; ans += node->cnt; } @@ -279,42 +291,6 @@ func sumPrefixScores(words []string) []int { #### TypeScript -```ts -function sumPrefixScores(words: string[]): number[] { - const map = new Map(); - - for (const word of words) { - const n = word.length; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - map.set(s, (map.get(s) ?? 0) + 1); - } - } - - return words.map(word => { - const n = word.length; - let count = 0; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - count += map.get(s); - } - return count; - }); -} -``` - - - - - - - -### Solution 2 - - - -#### TypeScript - ```ts class Trie { children: Array; diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.cpp b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.cpp index 648733eaa6e99..4df8ce5e3723c 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.cpp +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.cpp @@ -1,18 +1,16 @@ class Trie { private: - vector children; - int cnt; + Trie* children[26]{}; + int cnt = 0; public: - Trie() - : children(26) - , cnt(0) {} - void insert(string& w) { Trie* node = this; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) node->children[idx] = new Trie(); + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } node = node->children[idx]; ++node->cnt; } @@ -23,7 +21,9 @@ class Trie { int ans = 0; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) return ans; + if (!node->children[idx]) { + return ans; + } node = node->children[idx]; ans += node->cnt; } @@ -44,4 +44,4 @@ class Solution { } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.py b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.py index 73579eb370314..bef821c310c9f 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.py +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.py @@ -1,4 +1,6 @@ class Trie: + __slots__ = "children", "cnt" + def __init__(self): self.children = [None] * 26 self.cnt = 0 @@ -6,7 +8,7 @@ def __init__(self): def insert(self, w): node = self for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] @@ -16,7 +18,7 @@ def search(self, w): node = self ans = 0 for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: return ans node = node.children[idx] diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts index 8dbbaf5a2ff83..fa8217675a44e 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts @@ -1,21 +1,47 @@ -function sumPrefixScores(words: string[]): number[] { - const map = new Map(); +class Trie { + children: Array; + cnt: number; + + constructor() { + this.children = Array(26); + this.cnt = 0; + } - for (const word of words) { - const n = word.length; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - map.set(s, (map.get(s) ?? 0) + 1); + insert(w: string): void { + let node = this; + for (const c of w) { + const idx = c.charCodeAt(0) - 'a'.charCodeAt(0); + if (!node.children[idx]) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + node.cnt++; } } - return words.map(word => { - const n = word.length; - let count = 0; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - count += map.get(s); + search(w: string): number { + let node = this; + let ans = 0; + for (const c of w) { + const idx = c.charCodeAt(0) - 'a'.charCodeAt(0); + if (!node.children[idx]) { + return ans; + } + node = node.children[idx]; + ans += node.cnt; } - return count; - }); + return ans; + } +} + +function sumPrefixScores(words: string[]): number[] { + const trie = new Trie(); + for (const w of words) { + trie.insert(w); + } + let ans = []; + for (const w of words) { + ans.push(trie.search(w)); + } + return ans; } diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution2.ts b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution2.ts deleted file mode 100644 index fa8217675a44e..0000000000000 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution2.ts +++ /dev/null @@ -1,47 +0,0 @@ -class Trie { - children: Array; - cnt: number; - - constructor() { - this.children = Array(26); - this.cnt = 0; - } - - insert(w: string): void { - let node = this; - for (const c of w) { - const idx = c.charCodeAt(0) - 'a'.charCodeAt(0); - if (!node.children[idx]) { - node.children[idx] = new Trie(); - } - node = node.children[idx]; - node.cnt++; - } - } - - search(w: string): number { - let node = this; - let ans = 0; - for (const c of w) { - const idx = c.charCodeAt(0) - 'a'.charCodeAt(0); - if (!node.children[idx]) { - return ans; - } - node = node.children[idx]; - ans += node.cnt; - } - return ans; - } -} - -function sumPrefixScores(words: string[]): number[] { - const trie = new Trie(); - for (const w of words) { - trie.insert(w); - } - let ans = []; - for (const w of words) { - ans.push(trie.search(w)); - } - return ans; -} From 9a8894b869ba41b08ffed6c2bb2e0edf2a2bab96 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Fri, 2 Aug 2024 09:18:46 +0800 Subject: [PATCH 2/2] fix: update --- .../2416.Sum of Prefix Scores of Strings/README.md | 6 +----- .../2416.Sum of Prefix Scores of Strings/README_EN.md | 6 +----- .../2416.Sum of Prefix Scores of Strings/Solution.ts | 6 +----- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md index 77866649f6b80..8833573943b9c 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md @@ -333,11 +333,7 @@ function sumPrefixScores(words: string[]): number[] { for (const w of words) { trie.insert(w); } - let ans = []; - for (const w of words) { - ans.push(trie.search(w)); - } - return ans; + return words.map(w => trie.search(w)); } ``` diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md index 649cb15bc5949..808ab3f98788c 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md @@ -333,11 +333,7 @@ function sumPrefixScores(words: string[]): number[] { for (const w of words) { trie.insert(w); } - let ans = []; - for (const w of words) { - ans.push(trie.search(w)); - } - return ans; + return words.map(w => trie.search(w)); } ``` diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts index fa8217675a44e..a898ba5ece897 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts @@ -39,9 +39,5 @@ function sumPrefixScores(words: string[]): number[] { for (const w of words) { trie.insert(w); } - let ans = []; - for (const w of words) { - ans.push(trie.search(w)); - } - return ans; + return words.map(w => trie.search(w)); }