18. All Palindromic Partitions
β GFG solution to All Palindromic Partitions problem: find all ways to partition string into palindromic substrings using DP preprocessing and backtracking. π
The problem can be found at the following link: π Question Link
π§© Problem Description
Given a string s
, find all possible ways to partition it such that every substring in the partition is a palindrome.
A palindrome is a string that reads the same forward and backward.
π Examples
Example 1
Input: s = "geeks"
Output: [[g, e, e, k, s], [g, ee, k, s]]
Explanation: [g, e, e, k, s] and [g, ee, k, s] are the only partitions of "geeks" where each substring is a palindrome.
Example 2
Input: s = "abcba"
Output: [[a, b, c, b, a], [a, bcb, a], [abcba]]
Explanation: [a, b, c, b, a], [a, bcb, a] and [abcba] are the only partitions of "abcba" where each substring is a palindrome.
π Constraints
$1 \le s.size() \le 20$
β
My Approach
The optimal approach uses Dynamic Programming Preprocessing combined with Backtracking to efficiently find all palindromic partitions:
DP Preprocessing + Backtracking
Preprocessing Phase:
Build a 2D DP table
d[i][j]
to precompute whether substrings[i...j]
is a palindrome.Fill single characters (always palindromes).
Fill pairs of characters.
Fill longer substrings using the recurrence:
d[i][j] = (s[i] == s[j]) && d[i+1][j-1]
.
Backtracking Phase:
Start from index 0 and try all possible partitions.
For each position, check all substrings starting from that position.
If a substring is palindromic (using precomputed table), add it to current partition and recurse.
When we reach the end of string, add the current partition to results.
Backtrack by removing the last added substring.
Optimization Benefits:
O(1) palindrome checks during backtracking.
Avoids redundant palindrome computations.
Clean separation of concerns between preprocessing and partition generation.
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(nΒ² + 2βΏ), where n is the string length. The DP preprocessing takes O(nΒ²) to fill the palindrome table, and the backtracking generates at most 2βΏ partitions (each character can either start a new partition or continue the current one).
Expected Auxiliary Space Complexity: O(nΒ²), as we use a 2D DP table of size nΓn to store palindrome information. The recursion depth is O(n) and the space for storing results is not counted in auxiliary space.
π§βπ» Code (C++)
class Solution {
public:
vector<vector<string>> palinParts(string& s) {
int n = s.size();
vector<vector<bool>> d(n, vector<bool>(n));
for (int i = 0; i < n; i++) d[i][i] = true;
for (int i = 0; i < n - 1; i++) d[i][i + 1] = s[i] == s[i + 1];
for (int l = 3; l <= n; l++)
for (int i = 0; i <= n - l; i++) {
int j = i + l - 1;
d[i][j] = s[i] == s[j] && d[i + 1][j - 1];
}
vector<vector<string>> r;
vector<string> c;
function<void(int)> b = [&](int i) {
if (i == n) { r.push_back(c); return; }
for (int j = i; j < n; j++)
if (d[i][j]) {
c.push_back(s.substr(i, j - i + 1));
b(j + 1);
c.pop_back();
}
};
b(0);
return r;
}
};
π§βπ» Code (Java)
class Solution {
public ArrayList<ArrayList<String>> palinParts(String s) {
int n = s.length();
boolean[][] d = new boolean[n][n];
for (int i = 0; i < n; i++) d[i][i] = true;
for (int i = 0; i < n - 1; i++) d[i][i + 1] = s.charAt(i) == s.charAt(i + 1);
for (int l = 3; l <= n; l++)
for (int i = 0; i <= n - l; i++) {
int j = i + l - 1;
d[i][j] = s.charAt(i) == s.charAt(j) && d[i + 1][j - 1];
}
ArrayList<ArrayList<String>> r = new ArrayList<>();
ArrayList<String> c = new ArrayList<>();
dfs(0, s, d, c, r);
return r;
}
void dfs(int i, String s, boolean[][] d, ArrayList<String> c, ArrayList<ArrayList<String>> r) {
if (i == s.length()) { r.add(new ArrayList<>(c)); return; }
for (int j = i; j < s.length(); j++)
if (d[i][j]) {
c.add(s.substring(i, j + 1));
dfs(j + 1, s, d, c, r);
c.remove(c.size() - 1);
}
}
}
π Code (Python)
class Solution:
def palinParts(self, s):
n = len(s)
d = [[False]*n for _ in range(n)]
for i in range(n): d[i][i] = True
for i in range(n-1): d[i][i+1] = s[i] == s[i+1]
for l in range(3, n+1):
for i in range(n-l+1):
j = i + l - 1
d[i][j] = s[i] == s[j] and d[i+1][j-1]
r = []
def b(i, c):
if i == n: r.append(c[:]); return
for j in range(i, n):
if d[i][j]:
c.append(s[i:j+1])
b(j+1, c)
c.pop()
b(0, [])
return r
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated