Skip to content

feat: update solutions to lc problem: No.2416 #3348

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 2 commits into from
Aug 2, 2024
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
82 changes: 27 additions & 55 deletions solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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" 。
Expand Down Expand Up @@ -81,26 +81,38 @@ tags:

### 方法一:前缀树

用前缀树维护所有字符串的前缀以及每个前缀出现的次数
我们可以用前缀树来维护所有字符串的前缀以及每个前缀出现的次数

然后遍历每个字符串,累加每个前缀的出现次数即可。
定义前缀树节点结构体 `Trie`,包含两个属性:

时间复杂度 $O(n \times m)$。其中 $n$, $m$ 分别为字符串数组 `words` 的长度和其中字符串的最大长度。
- `children`:长度为 26 的数组,用于存储当前节点的子节点。
- `cnt`:当前节点的出现次数。

定义前缀树的两个方法:

- `insert`:插入一个字符串,将其前缀插入前缀树。
- `search`:搜索一个字符串,返回其前缀的出现次数。

我们遍历所有字符串,将每个字符串插入前缀树中。然后再遍历所有字符串,对每个字符串调用 `search` 方法,累加每个前缀的出现次数即可。

时间复杂度 $O(L)$,空间复杂度 $O(L)$,其中 $L$ 是所有字符串的总长度。

<!-- tabs:start -->

#### Python3

```python
class Trie:
__slots__ = "children", "cnt"

def __init__(self):
self.children = [None] * 26
self.cnt = 0

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]
Expand All @@ -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]
Expand Down Expand Up @@ -180,19 +192,17 @@ class Solution {
```cpp
class Trie {
private:
vector<Trie*> 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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
});
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- solution:start -->

### 方法二

<!-- tabs:start -->

#### TypeScript

```ts
class Trie {
children: Array<any>;
Expand Down Expand Up @@ -357,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));
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,28 +79,40 @@ Each prefix has a score of one, so the total is answer[0] = 1 + 1 + 1 + 1 = 4.

<!-- solution:start -->

### 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.

<!-- tabs:start -->

#### Python3

```python
class Trie:
__slots__ = "children", "cnt"

def __init__(self):
self.children = [None] * 26
self.cnt = 0

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]
Expand All @@ -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]
Expand Down Expand Up @@ -180,19 +192,17 @@ class Solution {
```cpp
class Trie {
private:
vector<Trie*> 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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
});
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- solution:start -->

### Solution 2

<!-- tabs:start -->

#### TypeScript

```ts
class Trie {
children: Array<any>;
Expand Down Expand Up @@ -357,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));
}
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
class Trie {
private:
vector<Trie*> 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;
}
Expand All @@ -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;
}
Expand All @@ -44,4 +44,4 @@ class Solution {
}
return ans;
}
};
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
class Trie:
__slots__ = "children", "cnt"

def __init__(self):
self.children = [None] * 26
self.cnt = 0

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]
Expand All @@ -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]
Expand Down
Loading
Loading