Skip to content

Commit fe2396a

Browse files
authored
feat: add solutions to lc problem: No.3597 (doocs#4534)
No.3697.Partition String
1 parent a358d8f commit fe2396a

File tree

12 files changed

+877
-6
lines changed

12 files changed

+877
-6
lines changed

solution/3500-3599/3597.Partition String/README.md

Lines changed: 310 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,32 +188,339 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3597.Pa
188188

189189
<!-- solution:start -->
190190

191-
### 方法一
191+
### 方法一:哈希表 + 模拟
192+
193+
我们可以用一个哈希表 $\textit{vis}$ 来记录已经出现过的段。然后我们遍历字符串 $s$,逐字符构建当前段 $t$,直到该段之前未曾出现过。每当我们构建出一个新的段时,就将其加入到结果列表中,并将其标记为已经出现过。
194+
195+
遍历结束后,返回结果列表即可。
196+
197+
时间复杂度 $O(n \times \sqrt{n})$,空间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。
192198

193199
<!-- tabs:start -->
194200

195201
#### Python3
196202

197203
```python
198-
204+
class Solution:
205+
def partitionString(self, s: str) -> List[str]:
206+
vis = set()
207+
ans = []
208+
t = ""
209+
for c in s:
210+
t += c
211+
if t not in vis:
212+
vis.add(t)
213+
ans.append(t)
214+
t = ""
215+
return ans
199216
```
200217

201218
#### Java
202219

203220
```java
204-
221+
class Solution {
222+
public List<String> partitionString(String s) {
223+
Set<String> vis = new HashSet<>();
224+
List<String> ans = new ArrayList<>();
225+
String t = "";
226+
for (char c : s.toCharArray()) {
227+
t += c;
228+
if (vis.add(t)) {
229+
ans.add(t);
230+
t = "";
231+
}
232+
}
233+
return ans;
234+
}
235+
}
205236
```
206237

207238
#### C++
208239

209240
```cpp
241+
class Solution {
242+
public:
243+
vector<string> partitionString(string s) {
244+
unordered_set<string> vis;
245+
vector<string> ans;
246+
string t = "";
247+
for (char c : s) {
248+
t += c;
249+
if (!vis.contains(t)) {
250+
vis.insert(t);
251+
ans.push_back(t);
252+
t = "";
253+
}
254+
}
255+
return ans;
256+
}
257+
};
258+
```
259+
260+
#### Go
261+
262+
```go
263+
func partitionString(s string) (ans []string) {
264+
vis := make(map[string]bool)
265+
t := ""
266+
for _, c := range s {
267+
t += string(c)
268+
if !vis[t] {
269+
vis[t] = true
270+
ans = append(ans, t)
271+
t = ""
272+
}
273+
}
274+
return
275+
}
276+
```
277+
278+
#### TypeScript
279+
280+
```ts
281+
function partitionString(s: string): string[] {
282+
const vis = new Set<string>();
283+
const ans: string[] = [];
284+
let t = '';
285+
for (const c of s) {
286+
t += c;
287+
if (!vis.has(t)) {
288+
vis.add(t);
289+
ans.push(t);
290+
t = '';
291+
}
292+
}
293+
return ans;
294+
}
295+
```
296+
297+
<!-- tabs:end -->
298+
299+
<!-- solution:end -->
300+
301+
<!-- solution:start -->
302+
303+
### 方法二:字符串哈希 + 哈希表 + 模拟
210304

305+
我们可以使用字符串哈希来加速段的查找。具体地,我们可以为每个段计算一个哈希值,并将其存储在一个哈希表中。这样,我们就可以在常数时间内判断一个段是否已经出现过。
306+
307+
具体地,我们首先根据字符串 $s$ 创建一个字符串哈希类 $\textit{Hashing}$,该类支持计算字符串的哈希值。然后,我们遍历字符串 $s$,用两个指针 $l$ 和 $r$ 来表示当前段的起始和结束位置(下标从 $1$ 开始)。每次扩展 $r$,我们计算当前段的哈希值 $x$,如果该哈希值不在哈希表中,则将其加入结果列表,并将其哈希值标记为已经出现过。否则,我们继续扩展 $r$,直到找到一个新的段。
308+
309+
遍历结束后,返回结果列表即可。
310+
311+
时间复杂度 $O(n)$,空间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。
312+
313+
<!-- tabs:start -->
314+
315+
#### Python3
316+
317+
```python
318+
class Hashing:
319+
__slots__ = ["mod", "h", "p"]
320+
321+
def __init__(
322+
self, s: Union[str, List[str]], base: int = 13331, mod: int = 998244353
323+
):
324+
self.mod = mod
325+
self.h = [0] * (len(s) + 1)
326+
self.p = [1] * (len(s) + 1)
327+
for i in range(1, len(s) + 1):
328+
self.h[i] = (self.h[i - 1] * base + ord(s[i - 1])) % mod
329+
self.p[i] = (self.p[i - 1] * base) % mod
330+
331+
def query(self, l: int, r: int) -> int:
332+
return (self.h[r] - self.h[l - 1] * self.p[r - l + 1]) % self.mod
333+
334+
335+
class Solution:
336+
def partitionString(self, s: str) -> List[str]:
337+
hashing = Hashing(s)
338+
vis = set()
339+
l = 1
340+
ans = []
341+
for r, c in enumerate(s, 1):
342+
x = hashing.query(l, r)
343+
if x not in vis:
344+
vis.add(x)
345+
ans.append(s[l - 1 : r])
346+
l = r + 1
347+
return ans
348+
```
349+
350+
#### Java
351+
352+
```java
353+
class Hashing {
354+
private final long[] p;
355+
private final long[] h;
356+
private final long mod;
357+
358+
public Hashing(String word) {
359+
this(word, 13331, 998244353);
360+
}
361+
362+
public Hashing(String word, long base, int mod) {
363+
int n = word.length();
364+
p = new long[n + 1];
365+
h = new long[n + 1];
366+
p[0] = 1;
367+
this.mod = mod;
368+
for (int i = 1; i <= n; i++) {
369+
p[i] = p[i - 1] * base % mod;
370+
h[i] = (h[i - 1] * base + word.charAt(i - 1)) % mod;
371+
}
372+
}
373+
374+
public long query(int l, int r) {
375+
return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod;
376+
}
377+
}
378+
379+
class Solution {
380+
public List<String> partitionString(String s) {
381+
Hashing hashing = new Hashing(s);
382+
Set<Long> vis = new HashSet<>();
383+
List<String> ans = new ArrayList<>();
384+
for (int l = 1, r = 1; r <= s.length(); ++r) {
385+
long x = hashing.query(l, r);
386+
if (vis.add(x)) {
387+
ans.add(s.substring(l - 1, r));
388+
l = r + 1;
389+
}
390+
}
391+
return ans;
392+
}
393+
}
394+
```
395+
396+
#### C++
397+
398+
```cpp
399+
class Hashing {
400+
private:
401+
vector<long long> p;
402+
vector<long long> h;
403+
long long mod;
404+
405+
public:
406+
Hashing(const string& word, long long base = 13331, long long mod = 998244353) {
407+
int n = word.size();
408+
p.resize(n + 1);
409+
h.resize(n + 1);
410+
p[0] = 1;
411+
this->mod = mod;
412+
for (int i = 1; i <= n; i++) {
413+
p[i] = (p[i - 1] * base) % mod;
414+
h[i] = (h[i - 1] * base + word[i - 1]) % mod;
415+
}
416+
}
417+
418+
long long query(int l, int r) const {
419+
return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod;
420+
}
421+
};
422+
423+
class Solution {
424+
public:
425+
vector<string> partitionString(const string& s) {
426+
Hashing hashing(s);
427+
unordered_set<long long> vis;
428+
vector<string> ans;
429+
int l = 1;
430+
for (int r = 1; r <= (int) s.size(); ++r) {
431+
long long x = hashing.query(l, r);
432+
if (!vis.contains(x)) {
433+
vis.insert(x);
434+
ans.push_back(s.substr(l - 1, r - l + 1));
435+
l = r + 1;
436+
}
437+
}
438+
return ans;
439+
}
440+
};
211441
```
212442
213443
#### Go
214444
215445
```go
446+
type Hashing struct {
447+
p, h []int64
448+
mod int64
449+
}
450+
451+
func NewHashing(s string, base, mod int64) *Hashing {
452+
n := len(s)
453+
p := make([]int64, n+1)
454+
h := make([]int64, n+1)
455+
p[0] = 1
456+
for i := 1; i <= n; i++ {
457+
p[i] = p[i-1] * base % mod
458+
h[i] = (h[i-1]*base + int64(s[i-1])) % mod
459+
}
460+
return &Hashing{p, h, mod}
461+
}
462+
463+
func (hs *Hashing) Query(l, r int) int64 {
464+
return (hs.h[r] - hs.h[l-1]*hs.p[r-l+1]%hs.mod + hs.mod) % hs.mod
465+
}
466+
467+
func partitionString(s string) (ans []string) {
468+
n := len(s)
469+
hashing := NewHashing(s, 13331, 998244353)
470+
vis := make(map[int64]bool)
471+
l := 1
472+
for r := 1; r <= n; r++ {
473+
x := hashing.Query(l, r)
474+
if !vis[x] {
475+
vis[x] = true
476+
ans = append(ans, s[l-1:r])
477+
l = r + 1
478+
}
479+
}
480+
return
481+
}
482+
```
216483

484+
#### TypeScript
485+
486+
```ts
487+
class Hashing {
488+
private p: bigint[];
489+
private h: bigint[];
490+
private mod: bigint;
491+
492+
constructor(s: string, base: bigint = 13331n, mod: bigint = 998244353n) {
493+
const n = s.length;
494+
this.mod = mod;
495+
this.p = new Array<bigint>(n + 1).fill(1n);
496+
this.h = new Array<bigint>(n + 1).fill(0n);
497+
for (let i = 1; i <= n; i++) {
498+
this.p[i] = (this.p[i - 1] * base) % mod;
499+
this.h[i] = (this.h[i - 1] * base + BigInt(s.charCodeAt(i - 1))) % mod;
500+
}
501+
}
502+
503+
query(l: number, r: number): bigint {
504+
return (this.h[r] - ((this.h[l - 1] * this.p[r - l + 1]) % this.mod) + this.mod) % this.mod;
505+
}
506+
}
507+
508+
function partitionString(s: string): string[] {
509+
const n = s.length;
510+
const hashing = new Hashing(s);
511+
const vis = new Set<string>();
512+
const ans: string[] = [];
513+
let l = 1;
514+
for (let r = 1; r <= n; r++) {
515+
const x = hashing.query(l, r).toString();
516+
if (!vis.has(x)) {
517+
vis.add(x);
518+
ans.push(s.slice(l - 1, r));
519+
l = r + 1;
520+
}
521+
}
522+
return ans;
523+
}
217524
```
218525

219526
<!-- tabs:end -->

0 commit comments

Comments
 (0)