From 0dbfd051102337a9cbbb2afefd5f3bb1b53b1670 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Sun, 29 Jun 2025 18:01:22 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3597 No.3697.Partition String --- .../3500-3599/3597.Partition String/README.md | 313 +++++++++++++++++- .../3597.Partition String/README_EN.md | 313 +++++++++++++++++- .../3597.Partition String/Solution.cpp | 17 + .../3597.Partition String/Solution.go | 13 + .../3597.Partition String/Solution.java | 15 + .../3597.Partition String/Solution.py | 12 + .../3597.Partition String/Solution.ts | 14 + .../3597.Partition String/Solution2.cpp | 42 +++ .../3597.Partition String/Solution2.go | 36 ++ .../3597.Partition String/Solution2.java | 41 +++ .../3597.Partition String/Solution2.py | 30 ++ .../3597.Partition String/Solution2.ts | 37 +++ 12 files changed, 877 insertions(+), 6 deletions(-) create mode 100644 solution/3500-3599/3597.Partition String/Solution.cpp create mode 100644 solution/3500-3599/3597.Partition String/Solution.go create mode 100644 solution/3500-3599/3597.Partition String/Solution.java create mode 100644 solution/3500-3599/3597.Partition String/Solution.py create mode 100644 solution/3500-3599/3597.Partition String/Solution.ts create mode 100644 solution/3500-3599/3597.Partition String/Solution2.cpp create mode 100644 solution/3500-3599/3597.Partition String/Solution2.go create mode 100644 solution/3500-3599/3597.Partition String/Solution2.java create mode 100644 solution/3500-3599/3597.Partition String/Solution2.py create mode 100644 solution/3500-3599/3597.Partition String/Solution2.ts diff --git a/solution/3500-3599/3597.Partition String/README.md b/solution/3500-3599/3597.Partition String/README.md index 98f48bc4d21da..c0cb0942bd997 100644 --- a/solution/3500-3599/3597.Partition String/README.md +++ b/solution/3500-3599/3597.Partition String/README.md @@ -188,32 +188,339 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3597.Pa -### 方法一 +### 方法一:哈希表 + 模拟 + +我们可以用一个哈希表 $\textit{vis}$ 来记录已经出现过的段。然后我们遍历字符串 $s$,逐字符构建当前段 $t$,直到该段之前未曾出现过。每当我们构建出一个新的段时,就将其加入到结果列表中,并将其标记为已经出现过。 + +遍历结束后,返回结果列表即可。 + +时间复杂度 $O(n \times \sqrt{n})$,空间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。 #### Python3 ```python - +class Solution: + def partitionString(self, s: str) -> List[str]: + vis = set() + ans = [] + t = "" + for c in s: + t += c + if t not in vis: + vis.add(t) + ans.append(t) + t = "" + return ans ``` #### Java ```java - +class Solution { + public List partitionString(String s) { + Set vis = new HashSet<>(); + List ans = new ArrayList<>(); + String t = ""; + for (char c : s.toCharArray()) { + t += c; + if (vis.add(t)) { + ans.add(t); + t = ""; + } + } + return ans; + } +} ``` #### C++ ```cpp +class Solution { +public: + vector partitionString(string s) { + unordered_set vis; + vector ans; + string t = ""; + for (char c : s) { + t += c; + if (!vis.contains(t)) { + vis.insert(t); + ans.push_back(t); + t = ""; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func partitionString(s string) (ans []string) { + vis := make(map[string]bool) + t := "" + for _, c := range s { + t += string(c) + if !vis[t] { + vis[t] = true + ans = append(ans, t) + t = "" + } + } + return +} +``` + +#### TypeScript + +```ts +function partitionString(s: string): string[] { + const vis = new Set(); + const ans: string[] = []; + let t = ''; + for (const c of s) { + t += c; + if (!vis.has(t)) { + vis.add(t); + ans.push(t); + t = ''; + } + } + return ans; +} +``` + + + + + + + +### 方法二:字符串哈希 + 哈希表 + 模拟 +我们可以使用字符串哈希来加速段的查找。具体地,我们可以为每个段计算一个哈希值,并将其存储在一个哈希表中。这样,我们就可以在常数时间内判断一个段是否已经出现过。 + +具体地,我们首先根据字符串 $s$ 创建一个字符串哈希类 $\textit{Hashing}$,该类支持计算字符串的哈希值。然后,我们遍历字符串 $s$,用两个指针 $l$ 和 $r$ 来表示当前段的起始和结束位置(下标从 $1$ 开始)。每次扩展 $r$,我们计算当前段的哈希值 $x$,如果该哈希值不在哈希表中,则将其加入结果列表,并将其哈希值标记为已经出现过。否则,我们继续扩展 $r$,直到找到一个新的段。 + +遍历结束后,返回结果列表即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。 + + + +#### Python3 + +```python +class Hashing: + __slots__ = ["mod", "h", "p"] + + def __init__( + self, s: Union[str, List[str]], base: int = 13331, mod: int = 998244353 + ): + self.mod = mod + self.h = [0] * (len(s) + 1) + self.p = [1] * (len(s) + 1) + for i in range(1, len(s) + 1): + self.h[i] = (self.h[i - 1] * base + ord(s[i - 1])) % mod + self.p[i] = (self.p[i - 1] * base) % mod + + def query(self, l: int, r: int) -> int: + return (self.h[r] - self.h[l - 1] * self.p[r - l + 1]) % self.mod + + +class Solution: + def partitionString(self, s: str) -> List[str]: + hashing = Hashing(s) + vis = set() + l = 1 + ans = [] + for r, c in enumerate(s, 1): + x = hashing.query(l, r) + if x not in vis: + vis.add(x) + ans.append(s[l - 1 : r]) + l = r + 1 + return ans +``` + +#### Java + +```java +class Hashing { + private final long[] p; + private final long[] h; + private final long mod; + + public Hashing(String word) { + this(word, 13331, 998244353); + } + + public Hashing(String word, long base, int mod) { + int n = word.length(); + p = new long[n + 1]; + h = new long[n + 1]; + p[0] = 1; + this.mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = p[i - 1] * base % mod; + h[i] = (h[i - 1] * base + word.charAt(i - 1)) % mod; + } + } + + public long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +} + +class Solution { + public List partitionString(String s) { + Hashing hashing = new Hashing(s); + Set vis = new HashSet<>(); + List ans = new ArrayList<>(); + for (int l = 1, r = 1; r <= s.length(); ++r) { + long x = hashing.query(l, r); + if (vis.add(x)) { + ans.add(s.substring(l - 1, r)); + l = r + 1; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Hashing { +private: + vector p; + vector h; + long long mod; + +public: + Hashing(const string& word, long long base = 13331, long long mod = 998244353) { + int n = word.size(); + p.resize(n + 1); + h.resize(n + 1); + p[0] = 1; + this->mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = (p[i - 1] * base) % mod; + h[i] = (h[i - 1] * base + word[i - 1]) % mod; + } + } + + long long query(int l, int r) const { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +}; + +class Solution { +public: + vector partitionString(const string& s) { + Hashing hashing(s); + unordered_set vis; + vector ans; + int l = 1; + for (int r = 1; r <= (int) s.size(); ++r) { + long long x = hashing.query(l, r); + if (!vis.contains(x)) { + vis.insert(x); + ans.push_back(s.substr(l - 1, r - l + 1)); + l = r + 1; + } + } + return ans; + } +}; ``` #### Go ```go +type Hashing struct { + p, h []int64 + mod int64 +} + +func NewHashing(s string, base, mod int64) *Hashing { + n := len(s) + p := make([]int64, n+1) + h := make([]int64, n+1) + p[0] = 1 + for i := 1; i <= n; i++ { + p[i] = p[i-1] * base % mod + h[i] = (h[i-1]*base + int64(s[i-1])) % mod + } + return &Hashing{p, h, mod} +} + +func (hs *Hashing) Query(l, r int) int64 { + return (hs.h[r] - hs.h[l-1]*hs.p[r-l+1]%hs.mod + hs.mod) % hs.mod +} + +func partitionString(s string) (ans []string) { + n := len(s) + hashing := NewHashing(s, 13331, 998244353) + vis := make(map[int64]bool) + l := 1 + for r := 1; r <= n; r++ { + x := hashing.Query(l, r) + if !vis[x] { + vis[x] = true + ans = append(ans, s[l-1:r]) + l = r + 1 + } + } + return +} +``` +#### TypeScript + +```ts +class Hashing { + private p: bigint[]; + private h: bigint[]; + private mod: bigint; + + constructor(s: string, base: bigint = 13331n, mod: bigint = 998244353n) { + const n = s.length; + this.mod = mod; + this.p = new Array(n + 1).fill(1n); + this.h = new Array(n + 1).fill(0n); + for (let i = 1; i <= n; i++) { + this.p[i] = (this.p[i - 1] * base) % mod; + this.h[i] = (this.h[i - 1] * base + BigInt(s.charCodeAt(i - 1))) % mod; + } + } + + query(l: number, r: number): bigint { + return (this.h[r] - ((this.h[l - 1] * this.p[r - l + 1]) % this.mod) + this.mod) % this.mod; + } +} + +function partitionString(s: string): string[] { + const n = s.length; + const hashing = new Hashing(s); + const vis = new Set(); + const ans: string[] = []; + let l = 1; + for (let r = 1; r <= n; r++) { + const x = hashing.query(l, r).toString(); + if (!vis.has(x)) { + vis.add(x); + ans.push(s.slice(l - 1, r)); + l = r + 1; + } + } + return ans; +} ``` diff --git a/solution/3500-3599/3597.Partition String/README_EN.md b/solution/3500-3599/3597.Partition String/README_EN.md index 303858229d954..15cf16d35fecf 100644 --- a/solution/3500-3599/3597.Partition String/README_EN.md +++ b/solution/3500-3599/3597.Partition String/README_EN.md @@ -186,32 +186,339 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3597.Pa -### Solution 1 +### Solution 1: Hash Table + Simulation + +We can use a hash table $\textit{vis}$ to record the segments that have already appeared. Then, we traverse the string $s$, building the current segment $t$ character by character until this segment has not appeared before. Each time we construct a new segment, we add it to the result list and mark it as seen. + +After the traversal, we simply return the result list. + +The time complexity is $O(n \times \sqrt{n})$, and the space complexity is $O(n)$, where $n$ is the length of the string $s$. #### Python3 ```python - +class Solution: + def partitionString(self, s: str) -> List[str]: + vis = set() + ans = [] + t = "" + for c in s: + t += c + if t not in vis: + vis.add(t) + ans.append(t) + t = "" + return ans ``` #### Java ```java - +class Solution { + public List partitionString(String s) { + Set vis = new HashSet<>(); + List ans = new ArrayList<>(); + String t = ""; + for (char c : s.toCharArray()) { + t += c; + if (vis.add(t)) { + ans.add(t); + t = ""; + } + } + return ans; + } +} ``` #### C++ ```cpp +class Solution { +public: + vector partitionString(string s) { + unordered_set vis; + vector ans; + string t = ""; + for (char c : s) { + t += c; + if (!vis.contains(t)) { + vis.insert(t); + ans.push_back(t); + t = ""; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func partitionString(s string) (ans []string) { + vis := make(map[string]bool) + t := "" + for _, c := range s { + t += string(c) + if !vis[t] { + vis[t] = true + ans = append(ans, t) + t = "" + } + } + return +} +``` + +#### TypeScript + +```ts +function partitionString(s: string): string[] { + const vis = new Set(); + const ans: string[] = []; + let t = ''; + for (const c of s) { + t += c; + if (!vis.has(t)) { + vis.add(t); + ans.push(t); + t = ''; + } + } + return ans; +} +``` + + + + + + + +### Solution 2: String Hashing + Hash Table + Simulation +We can use string hashing to speed up the lookup of segments. Specifically, we can compute a hash value for each segment and store it in a hash table. In this way, we can determine in constant time whether a segment has already appeared. + +In detail, we first create a string hashing class $\textit{Hashing}$ based on the string $s$, which supports computing the hash value of any substring. Then, we traverse the string $s$ using two pointers $l$ and $r$ to represent the start and end positions of the current segment (indices starting from $1$). Each time we extend $r$, we compute the hash value $x$ of the current segment. If this hash value is not in the hash table, we add the segment to the result list and mark its hash value as seen. Otherwise, we continue to extend $r$ until we find a new segment. + +After the traversal, we return the result list. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the string $s$. + + + +#### Python3 + +```python +class Hashing: + __slots__ = ["mod", "h", "p"] + + def __init__( + self, s: Union[str, List[str]], base: int = 13331, mod: int = 998244353 + ): + self.mod = mod + self.h = [0] * (len(s) + 1) + self.p = [1] * (len(s) + 1) + for i in range(1, len(s) + 1): + self.h[i] = (self.h[i - 1] * base + ord(s[i - 1])) % mod + self.p[i] = (self.p[i - 1] * base) % mod + + def query(self, l: int, r: int) -> int: + return (self.h[r] - self.h[l - 1] * self.p[r - l + 1]) % self.mod + + +class Solution: + def partitionString(self, s: str) -> List[str]: + hashing = Hashing(s) + vis = set() + l = 1 + ans = [] + for r, c in enumerate(s, 1): + x = hashing.query(l, r) + if x not in vis: + vis.add(x) + ans.append(s[l - 1 : r]) + l = r + 1 + return ans +``` + +#### Java + +```java +class Hashing { + private final long[] p; + private final long[] h; + private final long mod; + + public Hashing(String word) { + this(word, 13331, 998244353); + } + + public Hashing(String word, long base, int mod) { + int n = word.length(); + p = new long[n + 1]; + h = new long[n + 1]; + p[0] = 1; + this.mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = p[i - 1] * base % mod; + h[i] = (h[i - 1] * base + word.charAt(i - 1)) % mod; + } + } + + public long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +} + +class Solution { + public List partitionString(String s) { + Hashing hashing = new Hashing(s); + Set vis = new HashSet<>(); + List ans = new ArrayList<>(); + for (int l = 1, r = 1; r <= s.length(); ++r) { + long x = hashing.query(l, r); + if (vis.add(x)) { + ans.add(s.substring(l - 1, r)); + l = r + 1; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Hashing { +private: + vector p; + vector h; + long long mod; + +public: + Hashing(const string& word, long long base = 13331, long long mod = 998244353) { + int n = word.size(); + p.resize(n + 1); + h.resize(n + 1); + p[0] = 1; + this->mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = (p[i - 1] * base) % mod; + h[i] = (h[i - 1] * base + word[i - 1]) % mod; + } + } + + long long query(int l, int r) const { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +}; + +class Solution { +public: + vector partitionString(const string& s) { + Hashing hashing(s); + unordered_set vis; + vector ans; + int l = 1; + for (int r = 1; r <= (int) s.size(); ++r) { + long long x = hashing.query(l, r); + if (!vis.contains(x)) { + vis.insert(x); + ans.push_back(s.substr(l - 1, r - l + 1)); + l = r + 1; + } + } + return ans; + } +}; ``` #### Go ```go +type Hashing struct { + p, h []int64 + mod int64 +} + +func NewHashing(s string, base, mod int64) *Hashing { + n := len(s) + p := make([]int64, n+1) + h := make([]int64, n+1) + p[0] = 1 + for i := 1; i <= n; i++ { + p[i] = p[i-1] * base % mod + h[i] = (h[i-1]*base + int64(s[i-1])) % mod + } + return &Hashing{p, h, mod} +} + +func (hs *Hashing) Query(l, r int) int64 { + return (hs.h[r] - hs.h[l-1]*hs.p[r-l+1]%hs.mod + hs.mod) % hs.mod +} + +func partitionString(s string) (ans []string) { + n := len(s) + hashing := NewHashing(s, 13331, 998244353) + vis := make(map[int64]bool) + l := 1 + for r := 1; r <= n; r++ { + x := hashing.Query(l, r) + if !vis[x] { + vis[x] = true + ans = append(ans, s[l-1:r]) + l = r + 1 + } + } + return +} +``` +#### TypeScript + +```ts +class Hashing { + private p: bigint[]; + private h: bigint[]; + private mod: bigint; + + constructor(s: string, base: bigint = 13331n, mod: bigint = 998244353n) { + const n = s.length; + this.mod = mod; + this.p = new Array(n + 1).fill(1n); + this.h = new Array(n + 1).fill(0n); + for (let i = 1; i <= n; i++) { + this.p[i] = (this.p[i - 1] * base) % mod; + this.h[i] = (this.h[i - 1] * base + BigInt(s.charCodeAt(i - 1))) % mod; + } + } + + query(l: number, r: number): bigint { + return (this.h[r] - ((this.h[l - 1] * this.p[r - l + 1]) % this.mod) + this.mod) % this.mod; + } +} + +function partitionString(s: string): string[] { + const n = s.length; + const hashing = new Hashing(s); + const vis = new Set(); + const ans: string[] = []; + let l = 1; + for (let r = 1; r <= n; r++) { + const x = hashing.query(l, r).toString(); + if (!vis.has(x)) { + vis.add(x); + ans.push(s.slice(l - 1, r)); + l = r + 1; + } + } + return ans; +} ``` diff --git a/solution/3500-3599/3597.Partition String/Solution.cpp b/solution/3500-3599/3597.Partition String/Solution.cpp new file mode 100644 index 0000000000000..3fca78f23c30e --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution.cpp @@ -0,0 +1,17 @@ +class Solution { +public: + vector partitionString(string s) { + unordered_set vis; + vector ans; + string t = ""; + for (char c : s) { + t += c; + if (!vis.contains(t)) { + vis.insert(t); + ans.push_back(t); + t = ""; + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3500-3599/3597.Partition String/Solution.go b/solution/3500-3599/3597.Partition String/Solution.go new file mode 100644 index 0000000000000..0c27c0c550f24 --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution.go @@ -0,0 +1,13 @@ +func partitionString(s string) (ans []string) { + vis := make(map[string]bool) + t := "" + for _, c := range s { + t += string(c) + if !vis[t] { + vis[t] = true + ans = append(ans, t) + t = "" + } + } + return +} \ No newline at end of file diff --git a/solution/3500-3599/3597.Partition String/Solution.java b/solution/3500-3599/3597.Partition String/Solution.java new file mode 100644 index 0000000000000..05b0722fcb3bd --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution.java @@ -0,0 +1,15 @@ +class Solution { + public List partitionString(String s) { + Set vis = new HashSet<>(); + List ans = new ArrayList<>(); + String t = ""; + for (char c : s.toCharArray()) { + t += c; + if (vis.add(t)) { + ans.add(t); + t = ""; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3500-3599/3597.Partition String/Solution.py b/solution/3500-3599/3597.Partition String/Solution.py new file mode 100644 index 0000000000000..359502feef4c6 --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution.py @@ -0,0 +1,12 @@ +class Solution: + def partitionString(self, s: str) -> List[str]: + vis = set() + ans = [] + t = "" + for c in s: + t += c + if t not in vis: + vis.add(t) + ans.append(t) + t = "" + return ans diff --git a/solution/3500-3599/3597.Partition String/Solution.ts b/solution/3500-3599/3597.Partition String/Solution.ts new file mode 100644 index 0000000000000..110271aa943ac --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution.ts @@ -0,0 +1,14 @@ +function partitionString(s: string): string[] { + const vis = new Set(); + const ans: string[] = []; + let t = ''; + for (const c of s) { + t += c; + if (!vis.has(t)) { + vis.add(t); + ans.push(t); + t = ''; + } + } + return ans; +} diff --git a/solution/3500-3599/3597.Partition String/Solution2.cpp b/solution/3500-3599/3597.Partition String/Solution2.cpp new file mode 100644 index 0000000000000..2bb7a6c00d072 --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution2.cpp @@ -0,0 +1,42 @@ +class Hashing { +private: + vector p; + vector h; + long long mod; + +public: + Hashing(const string& word, long long base = 13331, long long mod = 998244353) { + int n = word.size(); + p.resize(n + 1); + h.resize(n + 1); + p[0] = 1; + this->mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = (p[i - 1] * base) % mod; + h[i] = (h[i - 1] * base + word[i - 1]) % mod; + } + } + + long long query(int l, int r) const { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +}; + +class Solution { +public: + vector partitionString(const string& s) { + Hashing hashing(s); + unordered_set vis; + vector ans; + int l = 1; + for (int r = 1; r <= (int) s.size(); ++r) { + long long x = hashing.query(l, r); + if (!vis.contains(x)) { + vis.insert(x); + ans.push_back(s.substr(l - 1, r - l + 1)); + l = r + 1; + } + } + return ans; + } +}; diff --git a/solution/3500-3599/3597.Partition String/Solution2.go b/solution/3500-3599/3597.Partition String/Solution2.go new file mode 100644 index 0000000000000..05faac8f83467 --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution2.go @@ -0,0 +1,36 @@ +type Hashing struct { + p, h []int64 + mod int64 +} + +func NewHashing(s string, base, mod int64) *Hashing { + n := len(s) + p := make([]int64, n+1) + h := make([]int64, n+1) + p[0] = 1 + for i := 1; i <= n; i++ { + p[i] = p[i-1] * base % mod + h[i] = (h[i-1]*base + int64(s[i-1])) % mod + } + return &Hashing{p, h, mod} +} + +func (hs *Hashing) Query(l, r int) int64 { + return (hs.h[r] - hs.h[l-1]*hs.p[r-l+1]%hs.mod + hs.mod) % hs.mod +} + +func partitionString(s string) (ans []string) { + n := len(s) + hashing := NewHashing(s, 13331, 998244353) + vis := make(map[int64]bool) + l := 1 + for r := 1; r <= n; r++ { + x := hashing.Query(l, r) + if !vis[x] { + vis[x] = true + ans = append(ans, s[l-1:r]) + l = r + 1 + } + } + return +} \ No newline at end of file diff --git a/solution/3500-3599/3597.Partition String/Solution2.java b/solution/3500-3599/3597.Partition String/Solution2.java new file mode 100644 index 0000000000000..2f87ff5780004 --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution2.java @@ -0,0 +1,41 @@ +class Hashing { + private final long[] p; + private final long[] h; + private final long mod; + + public Hashing(String word) { + this(word, 13331, 998244353); + } + + public Hashing(String word, long base, int mod) { + int n = word.length(); + p = new long[n + 1]; + h = new long[n + 1]; + p[0] = 1; + this.mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = p[i - 1] * base % mod; + h[i] = (h[i - 1] * base + word.charAt(i - 1)) % mod; + } + } + + public long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +} + +class Solution { + public List partitionString(String s) { + Hashing hashing = new Hashing(s); + Set vis = new HashSet<>(); + List ans = new ArrayList<>(); + for (int l = 1, r = 1; r <= s.length(); ++r) { + long x = hashing.query(l, r); + if (vis.add(x)) { + ans.add(s.substring(l - 1, r)); + l = r + 1; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3500-3599/3597.Partition String/Solution2.py b/solution/3500-3599/3597.Partition String/Solution2.py new file mode 100644 index 0000000000000..d9c1625d00e5c --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution2.py @@ -0,0 +1,30 @@ +class Hashing: + __slots__ = ["mod", "h", "p"] + + def __init__( + self, s: Union[str, List[str]], base: int = 13331, mod: int = 998244353 + ): + self.mod = mod + self.h = [0] * (len(s) + 1) + self.p = [1] * (len(s) + 1) + for i in range(1, len(s) + 1): + self.h[i] = (self.h[i - 1] * base + ord(s[i - 1])) % mod + self.p[i] = (self.p[i - 1] * base) % mod + + def query(self, l: int, r: int) -> int: + return (self.h[r] - self.h[l - 1] * self.p[r - l + 1]) % self.mod + + +class Solution: + def partitionString(self, s: str) -> List[str]: + hashing = Hashing(s) + vis = set() + l = 1 + ans = [] + for r, c in enumerate(s, 1): + x = hashing.query(l, r) + if x not in vis: + vis.add(x) + ans.append(s[l - 1 : r]) + l = r + 1 + return ans diff --git a/solution/3500-3599/3597.Partition String/Solution2.ts b/solution/3500-3599/3597.Partition String/Solution2.ts new file mode 100644 index 0000000000000..025661934dd0b --- /dev/null +++ b/solution/3500-3599/3597.Partition String/Solution2.ts @@ -0,0 +1,37 @@ +class Hashing { + private p: bigint[]; + private h: bigint[]; + private mod: bigint; + + constructor(s: string, base: bigint = 13331n, mod: bigint = 998244353n) { + const n = s.length; + this.mod = mod; + this.p = new Array(n + 1).fill(1n); + this.h = new Array(n + 1).fill(0n); + for (let i = 1; i <= n; i++) { + this.p[i] = (this.p[i - 1] * base) % mod; + this.h[i] = (this.h[i - 1] * base + BigInt(s.charCodeAt(i - 1))) % mod; + } + } + + query(l: number, r: number): bigint { + return (this.h[r] - ((this.h[l - 1] * this.p[r - l + 1]) % this.mod) + this.mod) % this.mod; + } +} + +function partitionString(s: string): string[] { + const n = s.length; + const hashing = new Hashing(s); + const vis = new Set(); + const ans: string[] = []; + let l = 1; + for (let r = 1; r <= n; r++) { + const x = hashing.query(l, r).toString(); + if (!vis.has(x)) { + vis.add(x); + ans.push(s.slice(l - 1, r)); + l = r + 1; + } + } + return ans; +}