2430. Maximum Deletions on a String
Description
You are given a string s consisting of only lowercase English letters. In one operation, you can:
- Delete the entire string
s, or - Delete the first
iletters ofsif the firstiletters ofsare equal to the followingiletters ins, for anyiin the range1 <= i <= s.length / 2.
For example, if s = "ababc", then in one operation, you could delete the first two letters of s to get "abc", since the first two letters of s and the following two letters of s are both equal to "ab".
Return the maximum number of operations needed to delete all of s.
Example 1:
Input: s = "abcabcdabc"
Output: 2
Explanation:
- Delete the first 3 letters ("abc") since the next 3 letters are equal. Now, s = "abcdabc".
- Delete all the letters.
We used 2 operations so return 2. It can be proven that 2 is the maximum number of operations needed.
Note that in the second operation we cannot delete "abc" again because the next occurrence of "abc" does not happen in the next 3 letters.
Example 2:
Input: s = "aaabaab"
Output: 4
Explanation:
- Delete the first letter ("a") since the next letter is equal. Now, s = "aabaab".
- Delete the first 3 letters ("aab") since the next 3 letters are equal. Now, s = "aab".
- Delete the first letter ("a") since the next letter is equal. Now, s = "ab".
- Delete all the letters.
We used 4 operations so return 4. It can be proven that 4 is the maximum number of operations needed.
Example 3:
Input: s = "aaaaa" Output: 5 Explanation: In each operation, we can delete the first letter of s.
Constraints:
1 <= s.length <= 4000sconsists only of lowercase English letters.
Solutions
Solution 1: Memoization Search
Thinking
With \(n\le 4000\), an operation deletes a prefix that equals the next block of the same length. Search states collapse to the start \(i\) of the remaining suffix. From \(i\), try lengths \(j\) and compare slices \(s[i:i+j]\) and \(s[i+j:i+2j]\); a match moves to \(i+j\) with one extra deletion. Deleting everything at once is always legal, so the answer is at least \(1\).
Memoize \(dfs(i)\). Slice comparison is linear in \(j\), and the total time \(O(n^2)\) fits the limit.
We design a function \(dfs(i)\), which represents the maximum number of operations needed to delete all characters from \(s[i..]\). The answer is \(dfs(0)\).
The calculation process of the function \(dfs(i)\) is as follows:
- If \(i \geq n\), then \(dfs(i) = 0\), return directly.
- Otherwise, we enumerate the length of the string \(j\), where \(1 \leq j \leq (n-1)/2\). If \(s[i..i+j] = s[i+j..i+j+j]\), we can delete \(s[i..i+j]\), then \(dfs(i)=max(dfs(i), dfs(i+j)+1)\). We need to enumerate all \(j\) to find the maximum value of \(dfs(i)\).
Here we need to quickly determine whether \(s[i..i+j]\) is equal to \(s[i+j..i+j+j]\). We can preprocess all the longest common prefixes of string \(s\), that is, \(g[i][j]\) represents the length of the longest common prefix of \(s[i..]\) and \(s[j..]\). In this way, we can quickly determine whether \(s[i..i+j]\) is equal to \(s[i+j..i+j+j]\), that is, \(g[i][i+j] \geq j\).
To avoid repeated calculations, we can use memoization search and use an array \(f\) to record the value of the function \(dfs(i)\).
The time complexity is \(O(n^2)\), and the space complexity is \(O(n^2)\). Here, \(n\) is the length of the string \(s\).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
Solution 2: Dynamic Programming
Thinking
Method 1 compares slices repeatedly and pays recursion overhead. Precompute LCP \(g[i][j]\) so equality is \(g[i][i+j]\ge j\) in \(O(1)\). Fill \(f[i]\) from the back; besides the LCP table the DP is one-dimensional.
We can change the memoization search in Solution 1 to dynamic programming. Define \(f[i]\) to represent the maximum number of operations needed to delete all characters from \(s[i..]\). Initially, \(f[i]=1\), and the answer is \(f[0]\).
We can enumerate \(i\) from back to front. For each \(i\), we enumerate the length of the string \(j\), where \(1 \leq j \leq (n-1)/2\). If \(s[i..i+j] = s[i+j..i+j+j]\), we can delete \(s[i..i+j]\), then \(f[i]=max(f[i], f[i+j]+1)\). We need to enumerate all \(j\) to find the maximum value of \(f[i]\).
The time complexity is \(O(n^2)\), and the space complexity is \(O(n)\). Here, \(n\) is the length of the string \(s\).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |