6868
6969<!-- solution:start -->
7070
71- ### 方法一:DFS
71+ ### 方法一:回溯 + 剪枝
7272
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}$ 的长度。
7482
7583<!-- tabs:start -->
7684
@@ -79,47 +87,52 @@ tags:
7987``` python
8088class Solution :
8189 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
8394 if i >= len (s):
84- nonlocal ans
85- ans = max (ans, t)
95+ ans = max (ans, len (st))
8696 return
8797 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 )
96106 return ans
97107```
98108
99109#### Java
100110
101111``` java
102112class Solution {
103- private Set<String > vis = new HashSet<> ();
104- private int ans = 1 ;
113+ private Set<String > st = new HashSet<> ();
114+ private int ans;
105115 private String s;
106116
107117 public int maxUniqueSplit (String s ) {
108118 this . s = s;
109- dfs(0 , 0 );
119+ dfs(0 );
110120 return ans;
111121 }
112122
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+ }
114127 if (i >= s. length()) {
115- ans = Math . max(ans, t );
128+ ans = Math . max(ans, st . size() );
116129 return ;
117130 }
118131 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 );
123136 }
124137 }
125138 }
@@ -131,57 +144,87 @@ class Solution {
131144``` cpp
132145class Solution {
133146public:
134- unordered_set<string > vis;
135- string s;
136- int ans = 1;
137-
138147 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;
155154 }
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;
157170 }
158171};
159172```
160173
161174#### Go
162175
163176```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))
172187 return
173188 }
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)
180194 }
181195 }
182196 }
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 ;
185228}
186229```
187230
0 commit comments