Skip to content

Commit 096c152

Browse files
committed
feat: 2213. Longest Substring of One Repeating Character : 线段树
1 parent a76887a commit 096c152

File tree

3 files changed

+194
-0
lines changed

3 files changed

+194
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
function longestRepeating (s: string, queryCharacters: string, queryIndices: number[]): number[] {
2+
const tree = new SegmentTree(0, s.length)
3+
for (let i = 0; i < s.length; i++) {
4+
tree.modify(i, s[i])
5+
}
6+
const ans = []
7+
for (let i = 0; i < queryCharacters.length; i++) {
8+
tree.modify(queryIndices[i], queryCharacters[i])
9+
ans.push(Math.max(...tree.query(0, s.length)))
10+
}
11+
return ans
12+
};
13+
14+
export declare const a: 1
15+
16+
class Node {
17+
start: number
18+
end: number
19+
maxLen: number[]
20+
leftMaxLen: number[]
21+
rightMaxLen: number[]
22+
left: null | Node = null
23+
right: null | Node = null
24+
constructor (start: number, end: number) {
25+
this.start = start
26+
this.end = end
27+
this.maxLen = Array(26).fill(0)
28+
this.leftMaxLen = Array(26).fill(0)
29+
this.rightMaxLen = Array(26).fill(0)
30+
}
31+
}
32+
33+
// https://www.acwing.com/activity/content/code/content/167900/
34+
class SegmentTree {
35+
root: Node
36+
constructor (start: number, end: number) {
37+
this.root = new Node(start, end)
38+
}
39+
40+
modify (pos: number, char: string) {
41+
this.modifyNode(this.root, pos, char)
42+
}
43+
44+
modifyNode (node: Node, pos: number, char: string) {
45+
if (node.start === pos && node.end === pos) {
46+
for (let i = 0; i < 26; i++) {
47+
node.leftMaxLen[i] = node.rightMaxLen[i] = node.maxLen[i] = char === (String.fromCharCode('a'.charCodeAt(0) + i)) ? 1 : 0
48+
}
49+
} else {
50+
this.pushdown(node)
51+
if (pos <= node.left!.end) this.modifyNode(node.left!, pos, char)
52+
if (pos >= node.right!.start) this.modifyNode(node.right!, pos, char)
53+
this.pushup(node)
54+
}
55+
}
56+
57+
// 这里 pushdown 的作用只是动态创建新节点
58+
pushdown (node: Node) {
59+
const mid = node.start + node.end >> 1
60+
node.left ??= new Node(node.start, mid)
61+
node.right ??= new Node(mid + 1, node.end)
62+
}
63+
64+
pushup (node: Node) {
65+
for (let i = 0; i < 26; i++) {
66+
node.leftMaxLen[i] = node.left!.leftMaxLen[i]
67+
if (node.left!.leftMaxLen[i] === node.left!.end - node.left!.start + 1) {
68+
node.leftMaxLen[i] = node.left!.leftMaxLen[i] + node.right!.leftMaxLen[i]
69+
}
70+
71+
node.rightMaxLen[i] = node.right!.rightMaxLen[i]
72+
if (node.right!.rightMaxLen[i] === node.right!.end - node.right!.start + 1) {
73+
node.rightMaxLen[i] = node.right!.rightMaxLen[i] + node.left!.rightMaxLen[i]
74+
}
75+
76+
node.maxLen[i] = Math.max(node.left!.maxLen[i], node.right!.maxLen[i], node.left!.rightMaxLen[i] + node.right!.leftMaxLen[i])
77+
}
78+
}
79+
80+
query (start: number, end: number) {
81+
return this.queryNode(this.root, start, end)
82+
}
83+
84+
arrayAdd (a: number[], b: number[]) {
85+
for (let i = 0; i < a.length; i++) a[i] += b[i]
86+
}
87+
88+
queryNode (node: Node, start: number, end: number) {
89+
if (start <= node.start && end >= node.end) return node.maxLen
90+
91+
this.pushdown(node)
92+
const sum = Array(26)
93+
if (start <= node.left!.end) this.arrayAdd(sum, this.queryNode(node.left!, start, end))
94+
if (end >= node.right!.start) this.arrayAdd(sum, this.queryNode(node.right!, start, end))
95+
return sum
96+
}
97+
}

leetcode/残酷刷题/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@
281281
## 线段树
282282

283283
- 715. Range Module
284+
- 2213. Longest Substring of One Repeating Character
284285

285286
## Links
286287

template-typescript.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
- [拓扑排序](#拓扑排序)
1616
- [字符串哈希](#字符串哈希)
1717
- [线段树](#线段树)
18+
- [单点修改](#单点修改)
19+
- [区间修改](#区间修改)
1820

1921
## 输入
2022

@@ -265,6 +267,100 @@ const hash = (i, j) => {
265267

266268
## 线段树
267269

270+
统一使用动态开点线段树。
271+
272+
### 单点修改
273+
274+
> https://leetcode.com/problems/longest-substring-of-one-repeating-character/
275+
276+
```ts
277+
class Node {
278+
start: number
279+
end: number
280+
maxLen: number[]
281+
leftMaxLen: number[]
282+
rightMaxLen: number[]
283+
left: null | Node = null
284+
right: null | Node = null
285+
constructor (start: number, end: number) {
286+
this.start = start
287+
this.end = end
288+
this.maxLen = Array(26).fill(0)
289+
this.leftMaxLen = Array(26).fill(0)
290+
this.rightMaxLen = Array(26).fill(0)
291+
}
292+
}
293+
294+
// https://www.acwing.com/activity/content/code/content/167900/
295+
class SegmentTree {
296+
root: Node
297+
constructor (start: number, end: number) {
298+
this.root = new Node(start, end)
299+
}
300+
301+
modify (pos: number, char: string) {
302+
this.modifyNode(this.root, pos, char)
303+
}
304+
305+
modifyNode (node: Node, pos: number, char: string) {
306+
if (node.start === pos && node.end === pos) {
307+
for (let i = 0; i < 26; i++) {
308+
node.leftMaxLen[i] = node.rightMaxLen[i] = node.maxLen[i] = char === (String.fromCharCode('a'.charCodeAt(0) + i)) ? 1 : 0
309+
}
310+
} else {
311+
this.pushdown(node)
312+
if (pos <= node.left!.end) this.modifyNode(node.left!, pos, char)
313+
if (pos >= node.right!.start) this.modifyNode(node.right!, pos, char)
314+
this.pushup(node)
315+
}
316+
}
317+
318+
// 这里 pushdown 的作用只是动态创建新节点
319+
pushdown (node: Node) {
320+
const mid = node.start + node.end >> 1
321+
node.left ??= new Node(node.start, mid)
322+
node.right ??= new Node(mid + 1, node.end)
323+
}
324+
325+
pushup (node: Node) {
326+
for (let i = 0; i < 26; i++) {
327+
node.leftMaxLen[i] = node.left!.leftMaxLen[i]
328+
if (node.left!.leftMaxLen[i] === node.left!.end - node.left!.start + 1) {
329+
node.leftMaxLen[i] = node.left!.leftMaxLen[i] + node.right!.leftMaxLen[i]
330+
}
331+
332+
node.rightMaxLen[i] = node.right!.rightMaxLen[i]
333+
if (node.right!.rightMaxLen[i] === node.right!.end - node.right!.start + 1) {
334+
node.rightMaxLen[i] = node.right!.rightMaxLen[i] + node.left!.rightMaxLen[i]
335+
}
336+
337+
node.maxLen[i] = Math.max(node.left!.maxLen[i], node.right!.maxLen[i], node.left!.rightMaxLen[i] + node.right!.leftMaxLen[i])
338+
}
339+
}
340+
341+
query (start: number, end: number) {
342+
return this.queryNode(this.root, start, end)
343+
}
344+
345+
arrayAdd (a: number[], b: number[]) {
346+
for (let i = 0; i < a.length; i++) a[i] += b[i]
347+
}
348+
349+
queryNode (node: Node, start: number, end: number) {
350+
if (start <= node.start && end >= node.end) return node.maxLen
351+
352+
this.pushdown(node)
353+
const sum = Array(26)
354+
if (start <= node.left!.end) this.arrayAdd(sum, this.queryNode(node.left!, start, end))
355+
if (end >= node.right!.start) this.arrayAdd(sum, this.queryNode(node.right!, start, end))
356+
return sum
357+
}
358+
}
359+
360+
```
361+
362+
### 区间修改
363+
268364
```ts
269365
enum Tracked {
270366
TRUE = 'TRUE',

0 commit comments

Comments
 (0)