Longest Chunked Palindrome Decomposition
HardPrompt
You are given a string text. You should split it to k substrings (subtext1, subtext2, ..., subtextk) such that:
subtextiis a non-empty string.- The concatenation of all the substrings is equal to
text(i.e.,subtext1 + subtext2 + ... + subtextk == text). subtexti == subtextk - i + 1for all valid values ofi(i.e.,1 <= i <= k).
Return the largest possible value of k.
Example 1:
Input: text = "ghiabcdefhelloadamhelloabcdefghi"
Output: 7
Explanation: We can split the string on "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)".Example 2:
Input: text = "merchant"
Output: 1
Explanation: We can split the string on "(merchant)".Example 3:
Input: text = "antaprezatepzapreanta"
Output: 11
Explanation: We can split the string on "(a)(nt)(a)(pre)(za)(tep)(za)(pre)(a)(nt)(a)".
Constraints:
1 <= text.length <= 1000textconsists only of lowercase English characters.
Approaches
3 approaches with complexity analysis and trade-offs.
This approach uses recursion with memoization to explore all possible valid decompositions and find the one with the maximum number of chunks. A function solve(i, j) is defined to compute the maximum number of chunks for the substring text[i...j]. This method guarantees correctness by exhaustively checking every possibility.
Algorithm
- Define a recursive function
solve(i, j)which computes the answer fortext.substring(i, j + 1). - Use a 2D array
memo[n][n]to store the results ofsolve(i, j)to avoid re-computation. - The base cases for the recursion are:
- If
i > j(empty substring), return 0. - If
i == j(single character), return 1.
- If
- In
solve(i, j), initialize the resultresto 1, representing the case where the entire substringtext[i...j]is a single chunk. - Iterate with a possible chunk length
lenfrom 1 up to(j - i + 1) / 2. - For each
len, check if the prefixtext[i...i+len-1]is equal to the suffixtext[j-len+1...j]. - If they are equal, it means we can form two chunks. The total number of chunks for this split would be
2 + solve(i + len, j - len). - Update
res = max(res, 2 + solve(i + len, j - len)). - Store the final
resinmemo[i][j]and return it. - The final answer is the result of
solve(0, n-1).
Walkthrough
The state dp(i, j) represents the solution for the substring text[i...j]. The function iterates through all possible lengths len for the first chunk, from 1 up to half the length of the current substring. For each len, it checks if the prefix of length len matches the suffix of length len. If they match, it makes a recursive call for the middle part dp(i + len, j - len) and considers 2 + dp(i + len, j - len) as a possible answer. The function takes the maximum over all possible splits, and also considers the case where the entire substring text[i...j] forms a single chunk (value of 1). A 2D array memo[n][n] is used to store the results to prevent recomputing the same subproblem.
class Solution { private int[][] memo; private String text; private int n; public int longestDecomposition(String text) { this.text = text; this.n = text.length(); this.memo = new int[n][n]; return solve(0, n - 1); } private int solve(int i, int j) { if (i > j) { return 0; } if (i == j) { return 1; } if (memo[i][j] != 0) { return memo[i][j]; } // The whole substring text[i..j] is one chunk int res = 1; // Try to find a matching prefix and suffix for (int len = 1; len <= (j - i + 1) / 2; len++) { if (text.substring(i, i + len).equals(text.substring(j - len + 1, j + 1))) { res = Math.max(res, 2 + solve(i + len, j - len)); } } return memo[i][j] = res; }}Complexity
Time
`O(N^4)`. There are `O(N^2)` states `(i, j)`. For each state of length `L`, we iterate `len` from 1 to `L/2`. The substring comparison takes `O(len)`. The work for one state is `sum_{len=1 to L/2} O(len) = O(L^2)`. The total complexity is `sum_{L=1 to N} (N-L+1) * O(L^2) = O(N^4)`.
Space
`O(N^2)` for the memoization table.
Trade-offs
Pros
It's a straightforward translation of the problem definition into a recursive solution, guaranteeing correctness by exploring all possibilities.
Cons
Extremely inefficient due to the high time complexity, making it infeasible for the given constraints (
N <= 1000).
Solutions
Solution
class Solution {public int longestDecomposition(String text) { int n = text.length(); if (n < 2) { return n; } for (int i = 1; i <= n >> 1; ++i) { if (text.substring(0, i).equals(text.substring(n - i))) { return 2 + longestDecomposition(text.substring(i, n - i)); } } return 1; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.