Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8fbe67c

Browse files
feat: add solutions to lc problem: No.1371 (doocs#3868)
No.1371.Find the Longest Substring Containing Vowels in Even Counts
1 parent 0a3f69a commit 8fbe67c

File tree

7 files changed

+249
-146
lines changed

7 files changed

+249
-146
lines changed

‎solution/1300-1399/1371.Find the Longest Substring Containing Vowels in Even Counts/README.md‎

Lines changed: 88 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,19 @@ tags:
6464

6565
<!-- solution:start -->
6666

67-
### 方法一
67+
### 方法一:前缀异或 + 数组或哈希表
68+
69+
根据题目描述,如果我们用一个数字表示字符串 $\textit{s}$ 的某个前缀中每个元音字母出现的次数的奇偶性,那么当两个前缀的这个数字相同时,这两个前缀的交集就是一个符合条件的子字符串。
70+
71+
我们可以用一个二进制数的低五位分别表示五个元音字母的奇偶性,其中第 $i$ 位为 1ドル$ 表示该元音字母在子字符串中出现了奇数次,为 0ドル$ 表示该元音字母在子字符串中出现了偶数次。
72+
73+
我们用 $\textit{mask}$ 表示这个二进制数,用一个数组或哈希表 $\textit{d}$ 记录每个 $\textit{mask}$ 第一次出现的位置。初始时,我们将 $\textit{d}[0] = -1,ドル表示空字符串的开始位置为 $-1$。
74+
75+
遍历字符串 $\textit{s},ドル如果遇到元音字母,就将 $\textit{mask}$ 的对应位取反。接下来,我们判断 $\textit{mask}$ 是否在之前出现过,如果出现过,那么我们就找到了一个符合条件的子字符串,其长度为当前位置减去 $\textit{mask}$ 上一次出现的位置。否则,我们将 $\textit{mask}$ 的当前位置存入 $\textit{d}$。
76+
77+
遍历结束后,我们就找到了最长的符合条件的子字符串。
78+
79+
时间复杂度 $O(n),ドル其中 $n$ 为字符串 $\textit{s}$ 的长度。空间复杂度 $O(1)$。
6880

6981
<!-- tabs:start -->
7082

@@ -73,40 +85,39 @@ tags:
7385
```python
7486
class Solution:
7587
def findTheLongestSubstring(self, s: str) -> int:
76-
pos = [inf] * 32
77-
pos[0] = -1
78-
vowels = 'aeiou'
79-
state = ans = 0
88+
d = {0: -1}
89+
ans = mask = 0
8090
for i, c in enumerate(s):
81-
for j, v in enumerate(vowels):
82-
if c == v:
83-
state ^= 1 << j
84-
ans = max(ans, i - pos[state])
85-
pos[state] = min(pos[state], i)
91+
if c in "aeiou":
92+
mask ^= 1 << (ord(c) - ord("a"))
93+
if mask in d:
94+
j = d[mask]
95+
ans = max(ans, i - j)
96+
else:
97+
d[mask] = i
8698
return ans
8799
```
88100

89101
#### Java
90102

91103
```java
92104
class Solution {
93-
94105
public int findTheLongestSubstring(String s) {
95-
int[] pos = new int[32];
96-
Arrays.fill(pos, Integer.MAX_VALUE);
97-
pos[0] = -1;
98106
String vowels = "aeiou";
99-
int state = 0;
100-
int ans = 0;
101-
for (int i = 0; i < s.length(); ++i) {
102-
char c = s.charAt(i);
107+
int[] d = new int[32];
108+
Arrays.fill(d, 1 << 29);
109+
d[0] = 0;
110+
int ans = 0, mask = 0;
111+
for (int i = 1; i <= s.length(); ++i) {
112+
char c = s.charAt(i - 1);
103113
for (int j = 0; j < 5; ++j) {
104114
if (c == vowels.charAt(j)) {
105-
state ^= (1 << j);
115+
mask ^= 1 << j;
116+
break;
106117
}
107118
}
108-
ans = Math.max(ans, i - pos[state]);
109-
pos[state] = Math.min(pos[state], i);
119+
ans = Math.max(ans, i - d[mask]);
120+
d[mask] = Math.min(d[mask], i);
110121
}
111122
return ans;
112123
}
@@ -119,16 +130,20 @@ class Solution {
119130
class Solution {
120131
public:
121132
int findTheLongestSubstring(string s) {
122-
vector<int> pos(32, INT_MAX);
123-
pos[0] = -1;
124133
string vowels = "aeiou";
125-
int state = 0, ans = 0;
126-
for (int i = 0; i < s.size(); ++i) {
127-
for (int j = 0; j < 5; ++j)
128-
if (s[i] == vowels[j])
129-
state ^= (1 << j);
130-
ans = max(ans, i - pos[state]);
131-
pos[state] = min(pos[state], i);
134+
vector<int> d(32, INT_MAX);
135+
d[0] = 0;
136+
int ans = 0, mask = 0;
137+
for (int i = 1; i <= s.length(); ++i) {
138+
char c = s[i - 1];
139+
for (int j = 0; j < 5; ++j) {
140+
if (c == vowels[j]) {
141+
mask ^= 1 << j;
142+
break;
143+
}
144+
}
145+
ans = max(ans, i - d[mask]);
146+
d[mask] = min(d[mask], i);
132147
}
133148
return ans;
134149
}
@@ -138,24 +153,49 @@ public:
138153
#### Go
139154
140155
```go
141-
func findTheLongestSubstring(s string) int {
142-
pos := make([]int, 32)
143-
for i := range pos {
144-
pos[i] = math.MaxInt32
145-
}
146-
pos[0] = -1
147-
vowels := "aeiou"
148-
state, ans := 0, 0
149-
for i, c := range s {
150-
for j, v := range vowels {
151-
if c == v {
152-
state ^= (1 << j)
153-
}
154-
}
155-
ans = max(ans, i-pos[state])
156-
pos[state] = min(pos[state], i)
157-
}
158-
return ans
156+
func findTheLongestSubstring(s string) (ans int) {
157+
vowels := "aeiou"
158+
d := [32]int{}
159+
for i := range d {
160+
d[i] = 1 << 29
161+
}
162+
d[0] = 0
163+
mask := 0
164+
for i := 1; i <= len(s); i++ {
165+
c := s[i-1]
166+
for j := 0; j < 5; j++ {
167+
if c == vowels[j] {
168+
mask ^= 1 << j
169+
break
170+
}
171+
}
172+
ans = max(ans, i-d[mask])
173+
d[mask] = min(d[mask], i)
174+
}
175+
return
176+
}
177+
```
178+
179+
#### TypeScript
180+
181+
```ts
182+
function findTheLongestSubstring(s: string): number {
183+
const vowels = 'aeiou';
184+
const d: number[] = Array(32).fill(1 << 29);
185+
d[0] = 0;
186+
let [ans, mask] = [0, 0];
187+
for (let i = 1; i <= s.length; i++) {
188+
const c = s[i - 1];
189+
for (let j = 0; j < 5; j++) {
190+
if (c === vowels[j]) {
191+
mask ^= 1 << j;
192+
break;
193+
}
194+
}
195+
ans = Math.max(ans, i - d[mask]);
196+
d[mask] = Math.min(d[mask], i);
197+
}
198+
return ans;
159199
}
160200
```
161201

‎solution/1300-1399/1371.Find the Longest Substring Containing Vowels in Even Counts/README_EN.md‎

Lines changed: 88 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,19 @@ tags:
6262

6363
<!-- solution:start -->
6464

65-
### Solution 1
65+
### Solution 1: Prefix XOR + Array or Hash Table
66+
67+
According to the problem description, if we use a number to represent the parity of the occurrences of each vowel in a prefix of the string $\textit{s},ドル then when two prefixes have the same number, the substring between these two prefixes is a valid substring.
68+
69+
We can use the lower five bits of a binary number to represent the parity of the five vowels, where the $i$-th bit being 1ドル$ means the vowel appears an odd number of times in the substring, and 0ドル$ means it appears an even number of times.
70+
71+
We use $\textit{mask}$ to represent this binary number and use an array or hash table $\textit{d}$ to record the first occurrence of each $\textit{mask}$. Initially, we set $\textit{d}[0] = -1,ドル indicating that the start position of the empty string is $-1$.
72+
73+
We traverse the string $\textit{s},ドル and if we encounter a vowel, we toggle the corresponding bit in $\textit{mask}$. Next, we check if $\textit{mask}$ has appeared before. If it has, we have found a valid substring, and its length is the current position minus the last occurrence of $\textit{mask}$. Otherwise, we store the current position of $\textit{mask}$ in $\textit{d}$.
74+
75+
After traversing the string, we will have found the longest valid substring.
76+
77+
The time complexity is $O(n),ドル where $n$ is the length of the string $\textit{s}$. The space complexity is $O(1)$.
6678

6779
<!-- tabs:start -->
6880

@@ -71,40 +83,39 @@ tags:
7183
```python
7284
class Solution:
7385
def findTheLongestSubstring(self, s: str) -> int:
74-
pos = [inf] * 32
75-
pos[0] = -1
76-
vowels = 'aeiou'
77-
state = ans = 0
86+
d = {0: -1}
87+
ans = mask = 0
7888
for i, c in enumerate(s):
79-
for j, v in enumerate(vowels):
80-
if c == v:
81-
state ^= 1 << j
82-
ans = max(ans, i - pos[state])
83-
pos[state] = min(pos[state], i)
89+
if c in "aeiou":
90+
mask ^= 1 << (ord(c) - ord("a"))
91+
if mask in d:
92+
j = d[mask]
93+
ans = max(ans, i - j)
94+
else:
95+
d[mask] = i
8496
return ans
8597
```
8698

8799
#### Java
88100

89101
```java
90102
class Solution {
91-
92103
public int findTheLongestSubstring(String s) {
93-
int[] pos = new int[32];
94-
Arrays.fill(pos, Integer.MAX_VALUE);
95-
pos[0] = -1;
96104
String vowels = "aeiou";
97-
int state = 0;
98-
int ans = 0;
99-
for (int i = 0; i < s.length(); ++i) {
100-
char c = s.charAt(i);
105+
int[] d = new int[32];
106+
Arrays.fill(d, 1 << 29);
107+
d[0] = 0;
108+
int ans = 0, mask = 0;
109+
for (int i = 1; i <= s.length(); ++i) {
110+
char c = s.charAt(i - 1);
101111
for (int j = 0; j < 5; ++j) {
102112
if (c == vowels.charAt(j)) {
103-
state ^= (1 << j);
113+
mask ^= 1 << j;
114+
break;
104115
}
105116
}
106-
ans = Math.max(ans, i - pos[state]);
107-
pos[state] = Math.min(pos[state], i);
117+
ans = Math.max(ans, i - d[mask]);
118+
d[mask] = Math.min(d[mask], i);
108119
}
109120
return ans;
110121
}
@@ -117,16 +128,20 @@ class Solution {
117128
class Solution {
118129
public:
119130
int findTheLongestSubstring(string s) {
120-
vector<int> pos(32, INT_MAX);
121-
pos[0] = -1;
122131
string vowels = "aeiou";
123-
int state = 0, ans = 0;
124-
for (int i = 0; i < s.size(); ++i) {
125-
for (int j = 0; j < 5; ++j)
126-
if (s[i] == vowels[j])
127-
state ^= (1 << j);
128-
ans = max(ans, i - pos[state]);
129-
pos[state] = min(pos[state], i);
132+
vector<int> d(32, INT_MAX);
133+
d[0] = 0;
134+
int ans = 0, mask = 0;
135+
for (int i = 1; i <= s.length(); ++i) {
136+
char c = s[i - 1];
137+
for (int j = 0; j < 5; ++j) {
138+
if (c == vowels[j]) {
139+
mask ^= 1 << j;
140+
break;
141+
}
142+
}
143+
ans = max(ans, i - d[mask]);
144+
d[mask] = min(d[mask], i);
130145
}
131146
return ans;
132147
}
@@ -136,24 +151,49 @@ public:
136151
#### Go
137152
138153
```go
139-
func findTheLongestSubstring(s string) int {
140-
pos := make([]int, 32)
141-
for i := range pos {
142-
pos[i] = math.MaxInt32
143-
}
144-
pos[0] = -1
145-
vowels := "aeiou"
146-
state, ans := 0, 0
147-
for i, c := range s {
148-
for j, v := range vowels {
149-
if c == v {
150-
state ^= (1 << j)
151-
}
152-
}
153-
ans = max(ans, i-pos[state])
154-
pos[state] = min(pos[state], i)
155-
}
156-
return ans
154+
func findTheLongestSubstring(s string) (ans int) {
155+
vowels := "aeiou"
156+
d := [32]int{}
157+
for i := range d {
158+
d[i] = 1 << 29
159+
}
160+
d[0] = 0
161+
mask := 0
162+
for i := 1; i <= len(s); i++ {
163+
c := s[i-1]
164+
for j := 0; j < 5; j++ {
165+
if c == vowels[j] {
166+
mask ^= 1 << j
167+
break
168+
}
169+
}
170+
ans = max(ans, i-d[mask])
171+
d[mask] = min(d[mask], i)
172+
}
173+
return
174+
}
175+
```
176+
177+
#### TypeScript
178+
179+
```ts
180+
function findTheLongestSubstring(s: string): number {
181+
const vowels = 'aeiou';
182+
const d: number[] = Array(32).fill(1 << 29);
183+
d[0] = 0;
184+
let [ans, mask] = [0, 0];
185+
for (let i = 1; i <= s.length; i++) {
186+
const c = s[i - 1];
187+
for (let j = 0; j < 5; j++) {
188+
if (c === vowels[j]) {
189+
mask ^= 1 << j;
190+
break;
191+
}
192+
}
193+
ans = Math.max(ans, i - d[mask]);
194+
d[mask] = Math.min(d[mask], i);
195+
}
196+
return ans;
157197
}
158198
```
159199

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
class Solution {
22
public:
33
int findTheLongestSubstring(string s) {
4-
vector<int> pos(32, INT_MAX);
5-
pos[0] = -1;
64
string vowels = "aeiou";
7-
int state = 0, ans = 0;
8-
for (int i = 0; i < s.size(); ++i) {
9-
for (int j = 0; j < 5; ++j)
10-
if (s[i] == vowels[j])
11-
state ^= (1 << j);
12-
ans = max(ans, i - pos[state]);
13-
pos[state] = min(pos[state], i);
5+
vector<int> d(32, INT_MAX);
6+
d[0] = 0;
7+
int ans = 0, mask = 0;
8+
for (int i = 1; i <= s.length(); ++i) {
9+
char c = s[i - 1];
10+
for (int j = 0; j < 5; ++j) {
11+
if (c == vowels[j]) {
12+
mask ^= 1 << j;
13+
break;
14+
}
15+
}
16+
ans = max(ans, i - d[mask]);
17+
d[mask] = min(d[mask], i);
1418
}
1519
return ans;
1620
}
17-
};
21+
};

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /