Skip to content

Commit 6c6522d

Browse files
committed
feat: add solutions to lc problem: No.2430
No.2430.Maximum Deletions on a String
1 parent c8dd797 commit 6c6522d

File tree

7 files changed

+439
-117
lines changed

7 files changed

+439
-117
lines changed

solution/2400-2499/2430.Maximum Deletions on a String/README.md

Lines changed: 206 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,28 @@
6565

6666
<!-- 这里可写通用的实现逻辑 -->
6767

68-
**方法一:动态规划 + 最长公共前缀**
68+
**方法一:记忆化搜索**
6969

70-
我们定义 $dp[i]$ 表示删除后缀 $s[i..]$ 字符所需的最大操作数。答案为 $dp[0]$。
70+
我们设计一个函数 $dfs(i)$,表示删除 $s[i..]$ 所有字符所需的最大操作数,那么答案就是 $dfs(0)$。
7171

72-
显然 $dp[i]$ 可以通过 $dp[i+j]$ 转移得到,其中 $j$ 是字符串长度,满足 $1 \leq j \leq (n-i / 2)$。
72+
函数 $dfs(i)$ 的计算过程如下:
7373

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)$ 的最大值即可。
7576

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$。
7778

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$ 的长度。
7990

8091
<!-- tabs:start -->
8192

@@ -87,12 +98,11 @@
8798
class Solution:
8899
def deleteString(self, s: str) -> int:
89100
@cache
90-
def dfs(i):
101+
def dfs(i: int) -> int:
91102
if i == n:
92103
return 0
93104
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):
96106
if s[i: i + j] == s[i + j: i + j + j]:
97107
ans = max(ans, 1 + dfs(i + j))
98108
return ans
@@ -105,45 +115,84 @@ class Solution:
105115
class Solution:
106116
def deleteString(self, s: str) -> int:
107117
n = len(s)
108-
lcp = [[0] * (n + 1) for _ in range(n + 1)]
118+
g = [[0] * (n + 1) for _ in range(n + 1)]
109119
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):
111121
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
114125
for i in range(n - 1, -1, -1):
115126
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]
119130
```
120131

121132
### **Java**
122133

123134
<!-- 这里可写当前语言的特殊实现逻辑 -->
124135

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+
125174
```java
126175
class Solution {
127176
public int deleteString(String s) {
128177
int n = s.length();
129-
int[][] lcp = new int[n + 1][n + 1];
178+
int[][] g = new int[n + 1][n + 1];
130179
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) {
132181
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;
134183
}
135184
}
136185
}
137-
int[] dp = new int[n];
138-
Arrays.fill(dp, 1);
186+
int[] f = new int[n];
139187
for (int i = n - 1; i >= 0; --i) {
188+
f[i] = 1;
140189
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);
143192
}
144193
}
145194
}
146-
return dp[0];
195+
return f[0];
147196
}
148197
}
149198
```
@@ -155,25 +204,61 @@ class Solution {
155204
public:
156205
int deleteString(string s) {
157206
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) {
162211
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;
164213
}
165214
}
166215
}
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;
170255
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);
173258
}
174259
}
175260
}
176-
return dp[0];
261+
return f[0];
177262
}
178263
};
179264
```
@@ -183,27 +268,69 @@ public:
183268
```go
184269
func deleteString(s string) int {
185270
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)
189274
}
190275
for i := n - 1; i >= 0; i-- {
191-
for j := n - 1; j >= 0; j-- {
276+
for j := i + 1; j < n; j++ {
192277
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)
194295
}
195296
}
297+
return f[i]
196298
}
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)
198325
for i := n - 1; i >= 0; i-- {
199-
dp[i] = 1
326+
f[i] = 1
200327
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)
203330
}
204331
}
205332
}
206-
return dp[0]
333+
return f[0]
207334
}
208335

209336
func max(a, b int) int {
@@ -217,7 +344,41 @@ func max(a, b int) int {
217344
### **TypeScript**
218345

219346
```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+
```
220368

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+
}
221382
```
222383

223384
### **...**

0 commit comments

Comments
 (0)