68
68
69
69
<!-- solution:start -->
70
70
71
- ### 方法一:DFS
71
+ ### 方法一:回溯 + 剪枝
72
72
73
- 经典 DFS 回溯问题。
73
+ 我们定义一个哈希表 $\textit{st}$,用于存储当前已经拆分出的子字符串。然后我们使用深度优先搜索的方式,尝试将字符串 $\textit{s}$ 拆分成若干个唯一的子字符串。
74
+
75
+ 具体地,我们设计一个函数 $\text{dfs}(i)$,表示我们正在考虑将 $\textit{s}[ i:] $ 进行拆分。
76
+
77
+ 在函数 $\text{dfs}(i)$ 中,我们首先判断如果当前已经拆分出的子字符串的数量加上剩余的字符数小于等于当前的答案,那么我们就没有必要继续拆分,直接返回。如果 $i \geq n$,那么说明我们已经完成了对整个字符串的拆分,我们更新答案为当前的子字符串数量和答案的较大值。否则,我们枚举当前子字符串的结束位置 $j$(不包括 $j$),并判断 $\textit{s}[ i..j)$ 是否已经被拆分出来。如果没有被拆分出来,我们将其加入到哈希表 $\textit{st}$ 中,并继续递归地考虑拆分剩余的部分。在递归调用结束后,我们需要将 $\textit{s}[ i..j)$ 从哈希表 $\textit{st}$ 中移除。
78
+
79
+ 最后,我们返回答案。
80
+
81
+ 时间复杂度 $O(n^2 \times 2^n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $\textit{s}$ 的长度。
74
82
75
83
<!-- tabs:start -->
76
84
@@ -79,47 +87,52 @@ tags:
79
87
``` python
80
88
class Solution :
81
89
def maxUniqueSplit (self , s : str ) -> int :
82
- def dfs (i , t ):
90
+ def dfs (i : int ):
91
+ nonlocal ans
92
+ if len (st) + len (s) - i <= ans:
93
+ return
83
94
if i >= len (s):
84
- nonlocal ans
85
- ans = max (ans, t)
95
+ ans = max (ans, len (st))
86
96
return
87
97
for j in range (i + 1 , len (s) + 1 ):
88
- if s[i:j] not in vis :
89
- vis .add(s[i:j])
90
- dfs(j, t + 1 )
91
- vis .remove(s[i:j])
92
-
93
- vis = set ()
94
- ans = 1
95
- dfs(0 , 0 )
98
+ if s[i:j] not in st :
99
+ st .add(s[i:j])
100
+ dfs(j)
101
+ st .remove(s[i:j])
102
+
103
+ ans = 0
104
+ st = set ()
105
+ dfs(0 )
96
106
return ans
97
107
```
98
108
99
109
#### Java
100
110
101
111
``` java
102
112
class Solution {
103
- private Set<String > vis = new HashSet<> ();
104
- private int ans = 1 ;
113
+ private Set<String > st = new HashSet<> ();
114
+ private int ans;
105
115
private String s;
106
116
107
117
public int maxUniqueSplit (String s ) {
108
118
this . s = s;
109
- dfs(0 , 0 );
119
+ dfs(0 );
110
120
return ans;
111
121
}
112
122
113
- private void dfs (int i , int t ) {
123
+ private void dfs (int i ) {
124
+ if (st. size() + s. length() - i <= ans) {
125
+ return ;
126
+ }
114
127
if (i >= s. length()) {
115
- ans = Math . max(ans, t );
128
+ ans = Math . max(ans, st . size() );
116
129
return ;
117
130
}
118
131
for (int j = i + 1 ; j <= s. length(); ++ j) {
119
- String x = s. substring(i, j);
120
- if (vis . add(x )) {
121
- dfs(j, t + 1 );
122
- vis . remove(x );
132
+ String t = s. substring(i, j);
133
+ if (st . add(t )) {
134
+ dfs(j);
135
+ st . remove(t );
123
136
}
124
137
}
125
138
}
@@ -131,57 +144,87 @@ class Solution {
131
144
``` cpp
132
145
class Solution {
133
146
public:
134
- unordered_set<string > vis;
135
- string s;
136
- int ans = 1;
137
-
138
147
int maxUniqueSplit(string s) {
139
- this->s = s;
140
- dfs(0, 0);
141
- return ans;
142
- }
143
-
144
- void dfs (int i, int t) {
145
- if (i >= s.size()) {
146
- ans = max(ans, t);
147
- return;
148
- }
149
- for (int j = i + 1; j <= s.size(); ++j) {
150
- string x = s.substr(i, j - i);
151
- if (!vis.count(x)) {
152
- vis.insert(x);
153
- dfs(j, t + 1);
154
- vis.erase(x);
148
+ unordered_set<string > st;
149
+ int n = s.size();
150
+ int ans = 0;
151
+ auto dfs = [ &] (this auto&& dfs, int i) -> void {
152
+ if (st.size() + n - i <= ans) {
153
+ return;
155
154
}
156
- }
155
+ if (i >= n) {
156
+ ans = max(ans, (int) st.size());
157
+ return;
158
+ }
159
+ for (int j = i + 1; j <= n; ++j) {
160
+ string t = s.substr(i, j - i);
161
+ if (!st.contains(t)) {
162
+ st.insert(t);
163
+ dfs(j);
164
+ st.erase(t);
165
+ }
166
+ }
167
+ };
168
+ dfs(0);
169
+ return ans;
157
170
}
158
171
};
159
172
```
160
173
161
174
#### Go
162
175
163
176
```go
164
- func maxUniqueSplit(s string) int {
165
- ans := 1
166
- vis := map[string]bool{}
167
-
168
- var dfs func(i, t int)
169
- dfs = func(i, t int) {
170
- if i >= len(s) {
171
- ans = max(ans, t)
177
+ func maxUniqueSplit(s string) (ans int) {
178
+ st := map[string]bool{}
179
+ n := len(s)
180
+ var dfs func(int)
181
+ dfs = func(i int) {
182
+ if len(st)+n-i <= ans {
183
+ return
184
+ }
185
+ if i >= n {
186
+ ans = max(ans, len(st))
172
187
return
173
188
}
174
- for j := i + 1; j <= len(s); j++ {
175
- x := s[i:j]
176
- if !vis[x] {
177
- vis[x] = true
178
- dfs(j, t+1)
179
- vis[x] = false
189
+ for j := i + 1; j <= n; j++ {
190
+ if t := s[i:j]; !st[t] {
191
+ st[t] = true
192
+ dfs(j)
193
+ delete(st, t)
180
194
}
181
195
}
182
196
}
183
- dfs(0, 0)
184
- return ans
197
+ dfs(0)
198
+ return
199
+ }
200
+ ```
201
+
202
+ #### TypeScript
203
+
204
+ ``` ts
205
+ function maxUniqueSplit(s : string ): number {
206
+ const n = s .length ;
207
+ const st = new Set <string >();
208
+ let ans = 0 ;
209
+ const dfs = (i : number ): void => {
210
+ if (st .size + n - i <= ans ) {
211
+ return ;
212
+ }
213
+ if (i >= n ) {
214
+ ans = Math .max (ans , st .size );
215
+ return ;
216
+ }
217
+ for (let j = i + 1 ; j <= n ; ++ j ) {
218
+ const t = s .slice (i , j );
219
+ if (! st .has (t )) {
220
+ st .add (t );
221
+ dfs (j );
222
+ st .delete (t );
223
+ }
224
+ }
225
+ };
226
+ dfs (0 );
227
+ return ans ;
185
228
}
186
229
```
187
230
0 commit comments