-
Notifications
You must be signed in to change notification settings - Fork 39
/
1542. Find Longest Awesome Substring.ts
85 lines (79 loc) · 2.3 KB
/
1542. Find Longest Awesome Substring.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class Heap<T=number> {
data: Array<T | null>
lt: (i: number, j: number) => boolean
constructor ()
constructor (data: T[])
constructor (cmp: (lhs: T, rhs: T) => boolean)
constructor (data: T[], cmp: (lhs: T, rhs: T) => boolean)
constructor (data: (T[] | ((lhs: T, rhs: T) => boolean)), cmp: (lhs: T, rhs: T) => boolean)
constructor (data: (T[] | ((lhs: T, rhs: T) => boolean)) = [], cmp = (lhs: T, rhs: T) => lhs < rhs) {
if (typeof data === 'function') {
cmp = data
data = []
}
this.data = [null, ...data]
this.lt = (i, j) => cmp(this.data[i]!, this.data[j]!)
for (let i = this.size(); i > 0; i--) this.heapify(i)
}
size (): number {
return this.data.length - 1
}
push (v: T): void {
this.data.push(v)
let i = this.size()
while ((i >> 1 !== 0) && this.lt(i, i >> 1)) this.swap(i, i >>= 1)
}
pop (): T {
this.swap(1, this.size())
const top = this.data.pop()
this.heapify(1)
return top!
}
top (): T { return this.data[1]! }
heapify (i: number): void {
while (true) {
let min = i
const [l, r, n] = [i * 2, i * 2 + 1, this.data.length]
if (l < n && this.lt(l, min)) min = l
if (r < n && this.lt(r, min)) min = r
if (min !== i) {
this.swap(i, min); i = min
} else break
}
}
swap (i: number, j: number): void {
const d = this.data;
[d[i], d[j]] = [d[j], d[i]]
}
}
/*
等价于求最长的串满足,这个串里面最多有一个数出现奇数次
状态 f 的每一位表示每个数出现的奇偶性
f[i] ^ f[j] 最多有 1 个 1,求最长的 [i, j] 区间
将 f[i] 反过来映射到下标 i,并且用最小堆存储即可,每次都可以拿到最小值
*/
function longestAwesome (s: string): number {
const h = new Map<number, Heap>()
let [f, ans] = [0, 0]
h.set(0, new Heap([-1]))
for (let i = 0; i < s.length; i++) {
f ^= 1 << (s.charCodeAt(i) - '0'.charCodeAt(0))
// 查找最小的满足条件的 j
if (h.get(f)) {
ans = Math.max(ans, i - h.get(f)!.top())
}
for (let k = 0; k < 10; k++) {
const g = f ^ (1 << k)
if (h.get(g)) {
ans = Math.max(ans, i - h.get(g)!.top())
}
}
// 将 i 放入 map 中
if (h.get(f)) {
h.get(f)?.push(i)
} else {
h.set(f, new Heap([i]))
}
}
return ans
};