65
65
66
66
<!-- 这里可写通用的实现逻辑 -->
67
67
68
- ** 方法一:动态规划 + 最长公共前缀 **
68
+ ** 方法一:记忆化搜索 **
69
69
70
- 我们定义 $dp [ i ] $ 表示删除后缀 $s[ i..] $ 字符所需的最大操作数。答案为 $dp [ 0 ] $。
70
+ 我们设计一个函数 $dfs(i)$,表示删除 $s[ i..] $ 所有字符所需的最大操作数,那么答案就是 $dfs(0) $。
71
71
72
- 显然 $dp [ i ] $ 可以通过 $dp [ i+j ] $ 转移得到,其中 $j$ 是字符串长度,满足 $1 \leq j \leq (n-i / 2)$。
72
+ 函数 $dfs(i)$ 的计算过程如下:
73
73
74
- 如果 $s[ i..i+j] = s[ i+j..i+j+j] $,那么我们可以删除 $s[ i..i+j] $,此时 $dp[ i] $ 可以转移到 $dp[ i+j] $。求 $dp[ i] $ 的最大值即可。
74
+ - 如果 $i \geq n$,那么 $dfs(i) = 0$,直接返回。
75
+ - 否则,我们枚举字符串的长度 $j$,其中 $1 \leq j \leq (n-1)/2$,如果 $s[ i..i+j] = s[ i+j..i+j+j] $,那么我们可以删除 $s[ i..i+j] $,此时 $dfs(i)=max(dfs(i), dfs(i+j)+1)$。我们需要枚举所有的 $j$,求 $dfs(i)$ 的最大值即可。
75
76
76
- 这里我们需要快速判断 $s[ i..i+j] = s[ i+j..i+j+j] $,我们可以使用最长公共前缀的方法,使用 $O(n^2)$ 预处理得到 $lcp [ i ] [ j ] $,表示从 $i$ 开始和从 $j$ 开始的最长公共前缀的长度 ,即 $lcp [ i] [ j ] $ 表示 $s[ i..] $ 和 $s[ j..] $ 的最长公共前缀的长度。然后我们就可以在 $O(1)$ 的时间内判断 $ s[ i..i+j] = s[ i+j..i+j+j] $。
77
+ 这里我们需要快速判断 $s[ i..i+j] $ 与 $ s[ i+j..i+j+j] $ 是否相等,我们可以预处理出字符串 $s$ 的所有最长公共前缀 ,即 $g [ i] [ j ] $ 表示 $s[ i..] $ 与 $s[ j..] $ 的最长公共前缀的长度。这样我们就可以快速判断 $ s[ i..i+j] $ 与 $ s[ i+j..i+j+j] $ 是否相等,即 $g [ i ] [ i+j ] \geq j $。
77
78
78
- 时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为字符串 $s$ 的长度。
79
+ 为了避免重复计算,我们可以使用记忆化搜索,用一个数组 $f$ 记录函数 $dfs(i)$ 的值。
80
+
81
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 是字符串 $s$ 的长度。
82
+
83
+ ** 方法二:动态规划**
84
+
85
+ 我们可以将方法一的记忆化搜索改为动态规划,定义 $f[ i] $ 表示删除 $s[ i..] $ 所有字符所需的最大操作数,初始时 $f[ i] =1$,答案为 $f[ 0] $。
86
+
87
+ 我们可以从后往前枚举 $i$,对于每个 $i$,我们枚举字符串的长度 $j$,其中 $1 \leq j \leq (n-1)/2$,如果 $s[ i..i+j] = s[ i+j..i+j+j] $,那么我们可以删除 $s[ i..i+j] $,此时 $f[ i] =max(f[ i] , f[ i+j] +1)$。我们需要枚举所有的 $j$,求 $f[ i] $ 的最大值即可。
88
+
89
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度。
79
90
80
91
<!-- tabs:start -->
81
92
87
98
class Solution :
88
99
def deleteString (self , s : str ) -> int :
89
100
@cache
90
- def dfs (i ) :
101
+ def dfs (i : int ) -> int :
91
102
if i == n:
92
103
return 0
93
104
ans = 1
94
- m = (n - i) >> 1
95
- for j in range (1 , m + 1 ):
105
+ for j in range (1 , (n - i) // 2 + 1 ):
96
106
if s[i: i + j] == s[i + j: i + j + j]:
97
107
ans = max (ans, 1 + dfs(i + j))
98
108
return ans
@@ -105,45 +115,84 @@ class Solution:
105
115
class Solution :
106
116
def deleteString (self , s : str ) -> int :
107
117
n = len (s)
108
- lcp = [[0 ] * (n + 1 ) for _ in range (n + 1 )]
118
+ g = [[0 ] * (n + 1 ) for _ in range (n + 1 )]
109
119
for i in range (n - 1 , - 1 , - 1 ):
110
- for j in range (n - 1 , - 1 , - 1 ):
120
+ for j in range (i + 1 , n ):
111
121
if s[i] == s[j]:
112
- lcp[i][j] = 1 + lcp[i + 1 ][j + 1 ]
113
- dp = [1 ] * n
122
+ g[i][j] = g[i + 1 ][j + 1 ] + 1
123
+
124
+ f = [1 ] * n
114
125
for i in range (n - 1 , - 1 , - 1 ):
115
126
for j in range (1 , (n - i) // 2 + 1 ):
116
- if lcp [i][i + j] >= j:
117
- dp [i] = max (dp [i], dp [i + j] + 1 )
118
- return dp [0 ]
127
+ if g [i][i + j] >= j:
128
+ f [i] = max (f [i], f [i + j] + 1 )
129
+ return f [0 ]
119
130
```
120
131
121
132
### ** Java**
122
133
123
134
<!-- 这里可写当前语言的特殊实现逻辑 -->
124
135
136
+ ``` java
137
+ class Solution {
138
+ private int n;
139
+ private Integer [] f;
140
+ private int [][] g;
141
+
142
+ public int deleteString (String s ) {
143
+ n = s. length();
144
+ f = new Integer [n];
145
+ g = new int [n + 1 ][n + 1 ];
146
+ for (int i = n - 1 ; i >= 0 ; -- i) {
147
+ for (int j = i + 1 ; j < n; ++ j) {
148
+ if (s. charAt(i) == s. charAt(j)) {
149
+ g[i][j] = g[i + 1 ][j + 1 ] + 1 ;
150
+ }
151
+ }
152
+ }
153
+ return dfs(0 );
154
+ }
155
+
156
+ private int dfs (int i ) {
157
+ if (i == n) {
158
+ return 0 ;
159
+ }
160
+ if (f[i] != null ) {
161
+ return f[i];
162
+ }
163
+ f[i] = 1 ;
164
+ for (int j = 1 ; j <= (n - i) / 2 ; ++ j) {
165
+ if (g[i][i + j] >= j) {
166
+ f[i] = Math . max(f[i], 1 + dfs(i + j));
167
+ }
168
+ }
169
+ return f[i];
170
+ }
171
+ }
172
+ ```
173
+
125
174
``` java
126
175
class Solution {
127
176
public int deleteString (String s ) {
128
177
int n = s. length();
129
- int [][] lcp = new int [n + 1 ][n + 1 ];
178
+ int [][] g = new int [n + 1 ][n + 1 ];
130
179
for (int i = n - 1 ; i >= 0 ; -- i) {
131
- for (int j = n - 1 ; j >= 0 ; -- j) {
180
+ for (int j = i + 1 ; j < n; ++ j) {
132
181
if (s. charAt(i) == s. charAt(j)) {
133
- lcp [i][j] = 1 + lcp [i + 1 ][j + 1 ];
182
+ g [i][j] = g [i + 1 ][j + 1 ] + 1 ;
134
183
}
135
184
}
136
185
}
137
- int [] dp = new int [n];
138
- Arrays . fill(dp, 1 );
186
+ int [] f = new int [n];
139
187
for (int i = n - 1 ; i >= 0 ; -- i) {
188
+ f[i] = 1 ;
140
189
for (int j = 1 ; j <= (n - i) / 2 ; ++ j) {
141
- if (lcp [i][i + j] >= j) {
142
- dp [i] = Math . max(dp [i], dp [i + j] + 1 );
190
+ if (g [i][i + j] >= j) {
191
+ f [i] = Math . max(f [i], f [i + j] + 1 );
143
192
}
144
193
}
145
194
}
146
- return dp [0 ];
195
+ return f [0 ];
147
196
}
148
197
}
149
198
```
@@ -155,25 +204,61 @@ class Solution {
155
204
public:
156
205
int deleteString(string s) {
157
206
int n = s.size();
158
- int lcp [ n + 1] [ n + 1 ] ;
159
- memset(lcp , 0, sizeof lcp );
160
- for (int i = n - 1; i >= 0 ; --i) {
161
- for (int j = n - 1; j >= 0; -- j) {
207
+ int g [ n + 1] [ n + 1 ] ;
208
+ memset(g , 0, sizeof(g) );
209
+ for (int i = n - 1; ~ i ; --i) {
210
+ for (int j = i + 1; j < n; ++ j) {
162
211
if (s[ i] == s[ j] ) {
163
- lcp [ i] [ j ] = 1 + lcp [ i + 1] [ j + 1 ] ;
212
+ g [ i] [ j ] = g [ i + 1] [ j + 1 ] + 1 ;
164
213
}
165
214
}
166
215
}
167
- int dp[ n] ;
168
- for (int i = n - 1; i >= 0; --i) {
169
- dp[ i] = 1;
216
+ int f[ n] ;
217
+ memset(f, 0, sizeof(f));
218
+ function<int(int)> dfs = [ &] (int i) -> int {
219
+ if (i == n) {
220
+ return 0;
221
+ }
222
+ if (f[ i] ) {
223
+ return f[ i] ;
224
+ }
225
+ f[ i] = 1;
226
+ for (int j = 1; j <= (n - i) / 2; ++j) {
227
+ if (g[ i] [ i + j ] >= j) {
228
+ f[ i] = max(f[ i] , 1 + dfs(i + j));
229
+ }
230
+ }
231
+ return f[ i] ;
232
+ };
233
+ return dfs(0);
234
+ }
235
+ };
236
+ ```
237
+
238
+ ```cpp
239
+ class Solution {
240
+ public:
241
+ int deleteString(string s) {
242
+ int n = s.size();
243
+ int g[n + 1][n + 1];
244
+ memset(g, 0, sizeof(g));
245
+ for (int i = n - 1; ~i; --i) {
246
+ for (int j = i + 1; j < n; ++j) {
247
+ if (s[i] == s[j]) {
248
+ g[i][j] = g[i + 1][j + 1] + 1;
249
+ }
250
+ }
251
+ }
252
+ int f[n];
253
+ for (int i = n - 1; ~i; --i) {
254
+ f[i] = 1;
170
255
for (int j = 1; j <= (n - i) / 2; ++j) {
171
- if (lcp [ i] [ i + j ] >= j) {
172
- dp [ i] = max(dp [ i] , dp [ i + j] + 1);
256
+ if (g [i][i + j] >= j) {
257
+ f [i] = max(f [i], f [i + j] + 1);
173
258
}
174
259
}
175
260
}
176
- return dp [ 0] ;
261
+ return f [0];
177
262
}
178
263
};
179
264
```
@@ -183,27 +268,69 @@ public:
183
268
``` go
184
269
func deleteString (s string ) int {
185
270
n := len (s)
186
- lcp := make([][]int, n+1)
187
- for i := range lcp {
188
- lcp [i] = make([]int, n+1)
271
+ g := make ([][]int , n+1 )
272
+ for i := range g {
273
+ g [i] = make ([]int , n+1 )
189
274
}
190
275
for i := n - 1 ; i >= 0 ; i-- {
191
- for j := n - 1; j >= 0 ; j-- {
276
+ for j := i + 1 ; j < n ; j++ {
192
277
if s[i] == s[j] {
193
- lcp[i][j] = 1 + lcp[i+1][j+1]
278
+ g[i][j] = g[i+1 ][j+1 ] + 1
279
+ }
280
+ }
281
+ }
282
+ f := make ([]int , n)
283
+ var dfs func (int ) int
284
+ dfs = func (i int ) int {
285
+ if i == n {
286
+ return 0
287
+ }
288
+ if f[i] > 0 {
289
+ return f[i]
290
+ }
291
+ f[i] = 1
292
+ for j := 1 ; j <= (n-i)/2 ; j++ {
293
+ if g[i][i+j] >= j {
294
+ f[i] = max (f[i], dfs (i+j)+1 )
194
295
}
195
296
}
297
+ return f[i]
196
298
}
197
- dp := make([]int, n)
299
+ return dfs (0 )
300
+ }
301
+
302
+ func max (a , b int ) int {
303
+ if a > b {
304
+ return a
305
+ }
306
+ return b
307
+ }
308
+ ```
309
+
310
+ ``` go
311
+ func deleteString (s string ) int {
312
+ n := len (s)
313
+ g := make ([][]int , n+1 )
314
+ for i := range g {
315
+ g[i] = make ([]int , n+1 )
316
+ }
317
+ for i := n - 1 ; i >= 0 ; i-- {
318
+ for j := i + 1 ; j < n; j++ {
319
+ if s[i] == s[j] {
320
+ g[i][j] = g[i+1 ][j+1 ] + 1
321
+ }
322
+ }
323
+ }
324
+ f := make ([]int , n)
198
325
for i := n - 1 ; i >= 0 ; i-- {
199
- dp [i] = 1
326
+ f [i] = 1
200
327
for j := 1 ; j <= (n-i)/2 ; j++ {
201
- if lcp [i][i+j] >= j {
202
- dp [i] = max(dp [i], dp [i+j]+1)
328
+ if g [i][i+j] >= j {
329
+ f [i] = max (f [i], f [i+j]+1 )
203
330
}
204
331
}
205
332
}
206
- return dp [0]
333
+ return f [0 ]
207
334
}
208
335
209
336
func max (a , b int ) int {
@@ -217,7 +344,41 @@ func max(a, b int) int {
217
344
### ** TypeScript**
218
345
219
346
``` ts
347
+ function deleteString(s : string ): number {
348
+ const n = s .length ;
349
+ const f: number [] = new Array (n ).fill (0 );
350
+ const dfs = (i : number ): number => {
351
+ if (i == n ) {
352
+ return 0 ;
353
+ }
354
+ if (f [i ] > 0 ) {
355
+ return f [i ];
356
+ }
357
+ f [i ] = 1 ;
358
+ for (let j = 1 ; j <= (n - i ) >> 1 ; ++ j ) {
359
+ if (s .slice (i , i + j ) == s .slice (i + j , i + j + j )) {
360
+ f [i ] = Math .max (f [i ], dfs (i + j ) + 1 );
361
+ }
362
+ }
363
+ return f [i ];
364
+ };
365
+ return dfs (0 );
366
+ }
367
+ ```
220
368
369
+ ``` ts
370
+ function deleteString(s : string ): number {
371
+ const n = s .length ;
372
+ const f: number [] = new Array (n ).fill (1 );
373
+ for (let i = n - 1 ; i >= 0 ; -- i ) {
374
+ for (let j = 1 ; j <= (n - i ) >> 1 ; ++ j ) {
375
+ if (s .slice (i , i + j ) === s .slice (i + j , i + j + j )) {
376
+ f [i ] = Math .max (f [i ], f [i + j ] + 1 );
377
+ }
378
+ }
379
+ }
380
+ return f [0 ];
381
+ }
221
382
```
222
383
223
384
### ** ...**
0 commit comments