Given a string str, a partitioning of the string is a palindrome partitioning if every sub-string of the partition is a palindrome, the task is to find the minimum number of cuts needed for palindrome partitioning of the given string.
Examples :
Input: str = “geek”
Output: 2
Explanation: We need to make minimum 2 cuts, i.e., “g ee k”Input: str = “aaaa”
Output: 0
Explanation: The string is already a palindrome.Input: str = “abcde”
Output: 4Input: str = “abbac”
Output: 1
Recursive Approach for Palindrome Partitioning:
This is the naive approach to solving the Palindrome Partitioning problem. In this approach, we will try to apply all possible partitions and at the end return the correct combination of partitions.
This approach is similar to that of Matrix Chain Multiplication problem.
In this approach, we recursively evaluate the following conditions:
- If the current string is a palindrome, then we simply return true, as Palindrome Partitioning is possible.
- Else, like the Matrix Chain Multiplication problem,
- we try making cuts at all possible places,
- recursively calculate the cost for each cut
- return the minimum value.
Below is the implementation of the above approach.
C++
// C++ Code for Palindrome Partitioning // Problem #include <bits/stdc++.h> using namespace std; // Function to Check if a substring is a palindrome bool isPalindrome(string String, int i, int j) { while (i < j) { if (String[i] != String[j]) return false ; i++; j--; } return true ; } // Function to find the minimum number of cuts needed for // palindrome partitioning int minPalPartion(string String, int i, int j) { // Base case: If the substring is empty or a palindrome, // no cuts needed if (i >= j || isPalindrome(String, i, j)) return 0; int ans = INT_MAX, count; // Iterate through all possible partitions and find the // minimum cuts needed for ( int k = i; k < j; k++) { count = minPalPartion(String, i, k) + minPalPartion(String, k + 1, j) + 1; ans = min(ans, count); } return ans; } // Driver code int main() { string str = "ababbbabbababa" ; // Find the minimum cuts needed for palindrome // partitioning and display the result cout << "Min cuts needed for Palindrome Partitioning is " << minPalPartion(str, 0, str.length() - 1) << endl; return 0; } |
Java
// public class PalindromePartitioning { // Function to Check if a substring is a palindrome static boolean isPalindrome(String str, int i, int j) { while (i < j) { if (str.charAt(i) != str.charAt(j)) return false ; i++; j--; } return true ; } // Function to find the minimum number of cuts needed // for palindrome partitioning static int minPalPartition(String str, int i, int j) { // Base case: If the substring is empty or a // palindrome, no cuts needed if (i >= j || isPalindrome(str, i, j)) return 0 ; int minCuts = Integer.MAX_VALUE; // Iterate through all possible partitions and find // the minimum cuts needed for ( int k = i; k < j; k++) { int cuts = minPalPartition(str, i, k) + minPalPartition(str, k + 1 , j) + 1 ; minCuts = Math.min(minCuts, cuts); } return minCuts; } // Driver code public static void main(String[] args) { String str = "ababbbabbababa" ; // Find the minimum cuts needed for palindrome // partitioning and display the result System.out.println( "Min cuts needed for Palindrome Partitioning is " + minPalPartition(str, 0 , str.length() - 1 )); } } |
Python3
# Function to Check if a substring is a palindrome def is_palindrome(string, i, j): while i < j: if string[i] ! = string[j]: return False i + = 1 j - = 1 return True # Function to find the minimum number of cuts needed for palindrome partitioning def min_pal_partition(string, i, j): # Base case: If the substring is empty or a palindrome, no cuts needed if i > = j or is_palindrome(string, i, j): return 0 ans = float ( 'inf' ) # Iterate through all possible partitions and find the minimum cuts needed for k in range (i, j): count = min_pal_partition(string, i, k) + \ min_pal_partition(string, k + 1 , j) + 1 ans = min (ans, count) return ans # Driver code if __name__ = = "__main__" : str = "ababbbabbababa" # Find the minimum cuts needed for palindrome partitioning and display the result print ( "Min cuts needed for Palindrome Partitioning is" , min_pal_partition( str , 0 , len ( str ) - 1 )) |
C#
using System; // Function to Check if a substring is a palindrome public class PalindromePartitioning { // Function to Check if a substring is a palindrome static bool IsPalindrome( string str, int i, int j) { while (i < j) { if (str[i] != str[j]) return false ; i++; j--; } return true ; } // Function to find the minimum number of cuts needed // for palindrome partitioning static int MinPalPartition( string str, int i, int j) { // Base case: If the substring is empty or a // palindrome, no cuts needed if (i >= j || IsPalindrome(str, i, j)) return 0; int minCuts = int .MaxValue; // Iterate through all possible partitions and find // the minimum cuts needed for ( int k = i; k < j; k++) { int cuts = MinPalPartition(str, i, k) + MinPalPartition(str, k + 1, j) + 1; minCuts = Math.Min(minCuts, cuts); } return minCuts; } // Driver code public static void Main( string [] args) { string str = "ababbbabbababa" ; // Find the minimum cuts needed for palindrome // partitioning and display the result Console.WriteLine( "Min cuts needed for Palindrome Partitioning is " + MinPalPartition(str, 0, str.Length - 1)); } } |
Javascript
<script> // Javascript code for Palindrome // Partitioning Problem // Function to Check if a substring is a palindrome function isPalindrome(String, i, j) { while (i < j) { if (String[i] != String[j]) return false ; i++; j--; } return true ; } // Function to find the minimum number of cuts needed // for palindrome partitioning function minPalPartion(String, i, j) { // Base case: If the substring is empty or a palindrome, // no cuts needed if (i >= j || isPalindrome(String, i, j)) return 0; let ans = Number.MAX_VALUE, count; // Iterate through all possible partitions and find the // minimum cuts needed for (let k = i; k < j; k++) { count = minPalPartion(String, i, k) + minPalPartion(String, k + 1, j) + 1; ans = Math.min(ans, count); } return ans; } // Driver code let str = "ababbbabbababa" ; // Find the minimum cuts needed for palindrome // partitioning and display the result document.write( "Min cuts needed for " + "Palindrome Partitioning is " + minPalPartion(str, 0, str.length - 1)); </script> |
Min cuts needed for Palindrome Partitioning is 3
Time Complexity: O(2n)
Auxiliary Space: O(n)
Optimising Overlapping Sub-problems in Recursive Approach for Palindrome Partitioning in (O(n3)):
The above recursive approach has overlapping subproblems, leading to redundant computations thereby resulting in exponential time complexity. This redundant computation can be solved by using Dynamic programming approach.
Here, we can use two 2D array C[][] and P[][], for storing the computed result.
- C[i][j] stores the minimum number of cuts needed for the substring str[i..j],
- while P[i][j] stores whether the substring str[i..j] is a palindrome or not.
- It starts with smaller substrings and gradually builds up to the entire string.
Below is the implementation of the above approach:
C++
// Dynamic Programming Solution for // Palindrome Partitioning Problem #include <bits/stdc++.h> using namespace std; // Returns the minimum number of cuts // needed to partition a string // such that every part is a palindrome int minPalPartion(string str) { // Get the length of the string int n = str.length(); // Create two arrays to build the solution in bottom up // manner // C[i][j] = Minimum number of cuts needed for // palindrome partitioning of substring str[i..j] int C[n][n]; // P[i][j] = true if substring str[i..j] is palindrome, // else false bool P[n][n]; // Note that C[i][j] is 0 if P[i][j] is true // Every substring of length 1 is a palindrome for ( int i = 0; i < n; i++) { P[i][i] = true ; C[i][i] = 0; } // L is substring length. Build the // solution in bottom up manner by // considering all substrings of // length starting from 2 to n. // The loop structure is same as Matrix // Chain Multiplication problem for ( int L = 2; L <= n; L++) { // For substring of length L, set // different possible starting indexes for ( int i = 0; i < n - L + 1; i++) { int j = i + L - 1; // Set ending index // If L is 2, then we just need to // compare two characters. Else // need to check two corner characters // and value of P[i+1][j-1] if (L == 2) P[i][j] = (str[i] == str[j]); else P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1]; // IF str[i..j] is palindrome, then C[i][j] is 0 if (P[i][j] == true ) C[i][j] = 0; else { // Make a cut at every possible // location starting from i to j, // and get the minimum cost cut. C[i][j] = INT_MAX; for ( int k = i; k <= j - 1; k++) C[i][j] = min( C[i][j], C[i][k] + C[k + 1][j] + 1); } } } // Return the min cut value for // complete string. i.e., str[0..n-1] return C[0][n - 1]; } // Driver code int main() { string str = "ababbbabbababa" ; cout << "Min cuts needed for Palindrome" " Partitioning is " << minPalPartion(str); return 0; } // This code is contributed by rathbhupendra |
C
// Dynamic Programming Solution for Palindrome Partitioning // Problem #include <limits.h> #include <stdio.h> #include <string.h> // A utility function to get minimum of two integers int min( int a, int b) { return (a < b) ? a : b; } // Returns the minimum number of cuts needed to partition a // string such that every part is a palindrome int minPalPartion( char * str) { // Get the length of the string int n = strlen (str); /* Create two arrays to build the solution in bottom up manner C[i][j] = Minimum number of cuts needed for palindrome partitioning of substring str[i..j] P[i][j] = true if substring str[i..j] is palindrome, else false Note that C[i][j] is 0 if P[i][j] is true */ int C[n][n]; bool P[n][n]; int i, j, k, L; // different looping variables // Every substring of length 1 is a palindrome for (i = 0; i < n; i++) { P[i][i] = true ; C[i][i] = 0; } /* L is substring length. Build the solution in bottom up manner by considering all substrings of length starting from 2 to n. The loop structure is same as Matrix Chain Multiplication problem ( See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/ for (L = 2; L <= n; L++) { // For substring of length L, set different possible // starting indexes for (i = 0; i < n - L + 1; i++) { j = i + L - 1; // Set ending index // If L is 2, then we just need to compare two // characters. Else need to check two corner // characters and value of P[i+1][j-1] if (L == 2) P[i][j] = (str[i] == str[j]); else P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1]; // IF str[i..j] is palindrome, then C[i][j] is 0 if (P[i][j] == true ) C[i][j] = 0; else { // Make a cut at every possible location // starting from i to j, and get the minimum // cost cut. C[i][j] = INT_MAX; for (k = i; k <= j - 1; k++) C[i][j] = min( C[i][j], C[i][k] + C[k + 1][j] + 1); } } } // Return the min cut value for complete string. i.e., // str[0..n-1] return C[0][n - 1]; } // Driver program to test above function int main() { char str[] = "ababbbabbababa" ; printf ( "Min cuts needed for Palindrome Partitioning is %d" , minPalPartion(str)); return 0; } |
Java
// Java Code for Palindrome Partitioning // Problem public class GFG { // Returns the minimum number of cuts needed // to partition a string such that every // part is a palindrome static int minPalPartion(String str) { // Get the length of the string int n = str.length(); /* Create two arrays to build the solution in bottom up manner C[i][j] = Minimum number of cuts needed for palindrome partitioning of substring str[i..j] P[i][j] = true if substring str[i..j] is palindrome, else false Note that C[i][j] is 0 if P[i][j] is true */ int [][] C = new int [n][n]; boolean [][] P = new boolean [n][n]; int i, j, k, L; // different looping variables // Every substring of length 1 is a palindrome for (i = 0 ; i < n; i++) { P[i][i] = true ; C[i][i] = 0 ; } /* L is substring length. Build the solution in bottom up manner by considering all substrings of length starting from 2 to n. The loop structure is same as Matrix Chain Multiplication problem ( See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/ for (L = 2 ; L <= n; L++) { // For substring of length L, set different // possible starting indexes for (i = 0 ; i < n - L + 1 ; i++) { j = i + L - 1 ; // Set ending index // If L is 2, then we just need to // compare two characters. Else need to // check two corner characters and value // of P[i+1][j-1] if (L == 2 ) P[i][j] = (str.charAt(i) == str.charAt(j)); else P[i][j] = (str.charAt(i) == str.charAt(j)) && P[i + 1 ][j - 1 ]; // IF str[i..j] is palindrome, then // C[i][j] is 0 if (P[i][j] == true ) C[i][j] = 0 ; else { // Make a cut at every possible // localtion starting from i to j, // and get the minimum cost cut. C[i][j] = Integer.MAX_VALUE; for (k = i; k <= j - 1 ; k++) C[i][j] = Integer.min( C[i][j], C[i][k] + C[k + 1 ][j] + 1 ); } } } // Return the min cut value for complete // string. i.e., str[0..n-1] return C[ 0 ][n - 1 ]; } // Driver program to test above function public static void main(String args[]) { String str = "ababbbabbababa" ; System.out.println( "Min cuts needed for " + "Palindrome Partitioning is " + minPalPartion(str)); } } // This code is contributed by Sumit Ghosh |
Python3
# Dynamic Programming Solution for # Palindrome Partitioning Problem # Returns the minimum number of # cuts needed to partition a string # such that every part is a palindrome def minPalPartion( str ): # Get the length of the string n = len ( str ) # Create two arrays to build the # solution in bottom up manner # C[i][j] = Minimum number of cuts # needed for palindrome # partitioning of substring str[i..j] # P[i][j] = true if substring str[i..j] # is palindrome, else false. Note that # C[i][j] is 0 if P[i][j] is true C = [[ 0 for i in range (n)] for i in range (n)] P = [[ False for i in range (n)] for i in range (n)] # different looping variables j = 0 k = 0 L = 0 # Every substring of length # 1 is a palindrome for i in range (n): P[i][i] = True C[i][i] = 0 # L is substring length. Build the # solution in bottom-up manner by # considering all substrings of # length starting from 2 to n. # The loop structure is the same as # Matrix Chain Multiplication problem # (See https://www.geeksforgeeks.org / matrix-chain-multiplication-dp-8/ ) for L in range ( 2 , n + 1 ): # For substring of length L, set # different possible starting indexes for i in range (n - L + 1 ): j = i + L - 1 # Set ending index # If L is 2, then we just need to # compare two characters. Else # need to check two corner characters # and value of P[i + 1][j-1] if L = = 2 : P[i][j] = ( str [i] = = str [j]) else : P[i][j] = (( str [i] = = str [j]) and P[i + 1 ][j - 1 ]) # IF str[i..j] is palindrome, # then C[i][j] is 0 if P[i][j] = = True : C[i][j] = 0 else : # Make a cut at every possible # location starting from i to j, # and get the minimum cost cut. C[i][j] = 100000000 for k in range (i, j): C[i][j] = min (C[i][j], C[i][k] + C[k + 1 ][j] + 1 ) # Return the min cut value for # complete string. i.e., str[0..n-1] return C[ 0 ][n - 1 ] # Driver code str = "ababbbabbababa" print ( 'Min cuts needed for Palindrome Partitioning is' , minPalPartion( str )) # This code is contributed # by Sahil shelangia |
C#
// C# Code for Palindrome Partitioning // Problem using System; class GFG { // Returns the minimum number of cuts needed // to partition a string such that every // part is a palindrome static int minPalPartion(String str) { // Get the length of the string int n = str.Length; /* Create two arrays to build the solution in bottom up manner C[i][j] = Minimum number of cuts needed for palindrome partitioning of substring str[i..j] P[i][j] = true if substring str[i..j] is palindrome, else false Note that C[i][j] is 0 if P[i][j] is true */ int [, ] C = new int [n, n]; bool [, ] P = new bool [n, n]; int i, j, k, L; // different looping variables // Every substring of length 1 is a palindrome for (i = 0; i < n; i++) { P[i, i] = true ; C[i, i] = 0; } /* L is substring length. Build the solution in bottom up manner by considering all substrings of length starting from 2 to n. The loop structure is same as Matrix Chain Multiplication problem ( See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/ for (L = 2; L <= n; L++) { // For substring of length L, set different // possible starting indexes for (i = 0; i < n - L + 1; i++) { j = i + L - 1; // Set ending index // If L is 2, then we just need to // compare two characters. Else need to // check two corner characters and value // of P[i+1][j-1] if (L == 2) P[i, j] = (str[i] == str[j]); else P[i, j] = (str[i] == str[j]) && P[i + 1, j - 1]; // IF str[i..j] is palindrome, then // C[i][j] is 0 if (P[i, j] == true ) C[i, j] = 0; else { // Make a cut at every possible // location starting from i to j, // and get the minimum cost cut. C[i, j] = int .MaxValue; for (k = i; k <= j - 1; k++) C[i, j] = Math.Min( C[i, j], C[i, k] + C[k + 1, j] + 1); } } } // Return the min cut value for complete // string. i.e., str[0..n-1] return C[0, n - 1]; } // Driver program public static void Main() { String str = "ababbbabbababa" ; Console.Write( "Min cuts needed for " + "Palindrome Partitioning is " + minPalPartion(str)); } } // This code is contributed by Sam007 |
Javascript
<script> // javascript Code for Palindrome Partitioning // Problem // Returns the minimum number of cuts needed // to partition a string such that every // part is a palindrome function minPalPartion( str) { // Get the length of the string var n = str.length; /* * Create two arrays to build the solution in bottom up manner C[i][j] = Minimum * number of cuts needed for palindrome partitioning of substring str[i..j] * P[i][j] = true if substring str[i..j] is palindrome, else false Note that * C[i][j] is 0 if P[i][j] is true */ var C = Array(n).fill().map(()=>Array(n).fill(0)); var P = Array(n).fill().map(()=>Array(n).fill( false )); var i, j, k, L; // different looping variables // Every substring of length 1 is a palindrome for (i = 0; i < n; i++) { P[i][i] = true ; C[i][i] = 0; } /* * L is substring length. Build the solution in bottom up manner by considering * all substrings of length starting from 2 to n. The loop structure is same as * Matrix Chain Multiplication problem ( See https:// * www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ ) */ for (L = 2; L <= n; L++) { // For substring of length L, set different // possible starting indexes for (i = 0; i < n - L + 1; i++) { j = i + L - 1; // Set ending index // If L is 2, then we just need to // compare two characters. Else need to // check two corner characters and value // of P[i+1][j-1] if (L == 2) P[i][j] = (str.charAt(i) == str.charAt(j)); else P[i][j] = (str.charAt(i) == str.charAt(j)) && P[i + 1][j - 1]; // IF str[i..j] is palindrome, then // C[i][j] is 0 if (P[i][j] == true ) C[i][j] = 0; else { // Make a cut at every possible // localtion starting from i to j, // and get the minimum cost cut. C[i][j] = Number.MAX_VALUE; for (k = i; k <= j - 1; k++) C[i][j] = Math.min(C[i][j], C[i][k] + C[k + 1][j] + 1); } } } // Return the min cut value for complete // string. i.e., str[0..n-1] return C[0][n - 1]; } // Driver program to test above function var str = "ababbbabbababa" ; document.write( "Min cuts needed for " + "Palindrome Partitioning is " + minPalPartion(str)); // This code is contributed by Rajput-Ji </script> |
PHP
<?php // Dynamic Programming Solution for Palindrome Partitioning Problem // Returns the minimum number of cuts needed to partition a string // such that every part is a palindrome function minPalPartion( $str ) { // Get the length of the string $n = strlen ( $str ); /* Create two arrays to build the solution in bottom up manner C[i][j] = Minimum number of cuts needed for palindrome partitioning of substring str[i..j] P[i][j] = true if substring str[i..j] is palindrome, else false Note that C[i][j] is 0 if P[i][j] is true */ $C = array_fill (0, $n , array_fill (0, $n , NULL)); $P = array_fill (false, $n , array_fill (false, $n , NULL)); // Every substring of length 1 is a palindrome for ( $i =0; $i < $n ; $i ++) { $P [ $i ][ $i ] = true; $C [ $i ][ $i ] = 0; } /* L is substring length. Build the solution in a bottom-up manner by considering all substrings of length starting from 2 to n. The loop structure is same as Matrix Chain Multiplication problem ( for ( $L =2; $L <= $n ; $L ++) { // For substring of length L, set different possible starting indexes for ( $i =0; $i < $n - $L +1; $i ++) { $j = $i + $L -1; // Set ending index // If L is 2, then we just need to compare two characters. Else // need to check two corner characters and value of P[i+1][j-1] if ( $L == 2) $P [ $i ][ $j ] = ( $str [ $i ] == $str [ $j ]); else $P [ $i ][ $j ] = ( $str [ $i ] == $str [ $j ]) && $P [ $i +1][ $j -1]; // IF str[i..j] is palindrome, then C[i][j] is 0 if ( $P [ $i ][ $j ] == true) $C [ $i ][ $j ] = 0; else { // Make a cut at every possible location starting from i to j, // and get the minimum cost cut. $C [ $i ][ $j ] = PHP_INT_MAX; for ( $k = $i ; $k <= $j -1; $k ++) $C [ $i ][ $j ] = min ( $C [ $i ][ $j ], $C [ $i ][ $k ] + $C [ $k +1][ $j ]+1); } } } // Return the min cut value for complete string. i.e., str[0..n-1] return $C [0][ $n -1]; } // Driver program to test the above function $str = "ababbbabbababa" ; echo "Min cuts needed for Palindrome Partitioning is " .minPalPartion( $str ); return 0; ?> |
Min cuts needed for Palindrome Partitioning is 3
Time Complexity: O(n3)
Auxiliary Space: O(n2)
Dynamic Programming Approach for Palindrome Partitioning in (O(n2)):
The problem can be solved by finding the suffix starting from j and ending at index i, (1 <= j <= i <= n – 1), which are palindromes. Hence, we can make a cut here that requires 1 + min cut from rest substring [0, j – 1]. For all such palindromic suffixes starting at j and ending at i, keep minimising in minCutDp[i]. Similarly, we need to compute results for all such i. (1 <= i <= n – 1) and finally, minCutDp[n – 1] will be the minimum number of cuts needed for palindrome partitioning of the given string.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h> using namespace std; // Function to generate all possible palindromic substring bool generatePalindrome(string& s, vector<vector< bool > >& pal) { int n = s.size(); // Initialize the palindrome matrix for single // characters for ( int i = 0; i < n; i++) { pal[i][i] = true ; } // Iterate over different lengths of substrings for ( int len = 2; len <= n; len++) { // Iterate over the starting positions of substrings // of current length for ( int i = 0; i <= n - len; i++) { // Calculate the ending position of the // substring int j = i + len - 1; // Check if the characters at the starting and // ending positions are equal and if the // substring between them is a palindrome or a // single character if (s[i] == s[j] && (len == 2 || pal[i + 1][j - 1])) { // Mark the substring from i to j as a // palindrome pal[i][j] = true ; } } } } // Function to calculate the minimum number of cuts required // to make all substrings of 's' palindromic int minCut(string s) { if (s.empty()) return 0; int n = s.size(); // 2D vector to store whether substring [i, j] is a // palindrome vector<vector< bool > > pal(n, vector< bool >(n, false )); generatePalindrome(s, pal); // vector to store minimum cuts required to make // substring [i, n-1] palindromic vector< int > minCutDp(n, INT_MAX); // There is no cut required for single character // as it is always palindrome minCutDp[0] = 0; // Iterate over the given string for ( int i = 1; i < n; i++) { // Check if string 0 to i is palindrome. // Then minCut require will be 0. if (pal[0][i]) { minCutDp[i] = 0; } else { for ( int j = i; j >= 1; j--) { // If s[i] and s[j] are equal and the inner // substring [i+1, j-1] is a palindrome or // it has a length of 1 if (pal[j][i]) { // Update the minimum cuts required if // cutting at position 'j+1' results in // a smaller value if (minCutDp[j - 1] + 1 < minCutDp[i]) minCutDp[i] = minCutDp[j - 1] + 1; } } } } // Return the minimum cuts required for the entire // string 's' return minCutDp[n - 1]; } int main() { string str = "ababbbabbababa" ; int cuts = minCut(str); cout << "Minimum cuts required: " << cuts << endl; return 0; } |
Java
import java.util.Arrays; public class GFG { // Function to generate all possible palindromic // substrings static boolean generatePalindrome(String s, boolean [][] pal) { int n = s.length(); // Initialize the palindrome matrix for single // characters for ( int i = 0 ; i < n; i++) { pal[i][i] = true ; } // Iterate over different lengths of substrings for ( int len = 2 ; len <= n; len++) { // Iterate over the starting positions of // substrings of current length for ( int i = 0 ; i <= n - len; i++) { // Calculate the ending position of the // substring int j = i + len - 1 ; // Check if the characters at the starting // and ending positions are equal and if the // substring between them is a palindrome or // a single character if (s.charAt(i) == s.charAt(j) && (len == 2 || pal[i + 1 ][j - 1 ])) { // Mark the substring from i to j as a // palindrome pal[i][j] = true ; } } } return true ; } // Function to calculate the minimum number of cuts // required to make all substrings of 's' palindromic static int minCut(String s) { if (s.isEmpty()) return 0 ; int n = s.length(); // 2D array to store whether substring [i, j] is a // palindrome boolean [][] pal = new boolean [n][n]; generatePalindrome(s, pal); // Array to store minimum cuts required to make // substring [i, n-1] palindromic int [] minCutDp = new int [n]; Arrays.fill(minCutDp, Integer.MAX_VALUE); // There is no cut required for single character // as it is always palindrome minCutDp[ 0 ] = 0 ; // Iterate over the given string for ( int i = 1 ; i < n; i++) { // Check if string 0 to i is palindrome. // Then minCut require will be 0. if (pal[ 0 ][i]) { minCutDp[i] = 0 ; } else { for ( int j = i; j >= 1 ; j--) { // If s[i] and s[j] are equal and the // inner substring [i+1, j-1] is a // palindrome or it has a length of 1 if (pal[j][i]) { // Update the minimum cuts required // if cutting at position 'j+1' // results in a smaller value if (minCutDp[j - 1 ] + 1 < minCutDp[i]) minCutDp[i] = minCutDp[j - 1 ] + 1 ; } } } } // Return the minimum cuts required for the entire // string 's' return minCutDp[n - 1 ]; } public static void main(String[] args) { String str = "ababbbabbababa" ; int cuts = minCut(str); System.out.println( "Minimum cuts required: " + cuts); } } |
Python3
def generate_palindrome(s, pal): n = len (s) # Initialize the palindrome matrix for single characters for i in range (n): pal[i][i] = True # Iterate over different lengths of substrings for length in range ( 2 , n + 1 ): # Iterate over the starting positions of substrings of current length for i in range (n - length + 1 ): # Calculate the ending position of the substring j = i + length - 1 # Check if the characters at the starting and ending positions are equal # and if the substring between them is a palindrome or a single character if s[i] = = s[j] and (length = = 2 or pal[i + 1 ][j - 1 ]): # Mark the substring from i to j as a palindrome pal[i][j] = True def min_cut(s): if not s: return 0 n = len (s) # 2D list to store whether substring [i, j] is a palindrome pal = [[ False ] * n for _ in range (n)] generate_palindrome(s, pal) # List to store minimum cuts required to make substring [i, n-1] palindromic min_cut_dp = [ float ( 'inf' )] * n # There is no cut required for a single character as it is always a palindrome min_cut_dp[ 0 ] = 0 # Iterate over the given string for i in range ( 1 , n): # Check if string 0 to i is a palindrome. Then minCut required will be 0. if pal[ 0 ][i]: min_cut_dp[i] = 0 else : for j in range (i, 0 , - 1 ): # If s[i] and s[j] are equal and the inner substring [i+1, j-1] # is a palindrome or it has a length of 1 if pal[j][i]: # Update the minimum cuts required if cutting at position 'j+1' results in a smaller value if min_cut_dp[j - 1 ] + 1 < min_cut_dp[i]: min_cut_dp[i] = min_cut_dp[j - 1 ] + 1 # Return the minimum cuts required for the entire string 's' return min_cut_dp[n - 1 ] # Driver code if __name__ = = "__main__" : str = "ababbbabbababa" cuts = min_cut( str ) print ( "Minimum cuts required:" , cuts) |
C#
using System; class Program { // Function to generate all possible palindromic // substrings static void GeneratePalindrome( string s, bool [, ] pal) { int n = s.Length; // Initialize the palindrome matrix for single // characters for ( int i = 0; i < n; i++) { pal[i, i] = true ; } // Iterate over different lengths of substrings for ( int len = 2; len <= n; len++) { // Iterate over the starting positions of // substrings of current length for ( int i = 0; i <= n - len; i++) { // Calculate the ending position of the // substring int j = i + len - 1; // Check if the characters at the starting // and ending positions are equal and if the // substring between them is a palindrome or // a single character if (s[i] == s[j] && (len == 2 || pal[i + 1, j - 1])) { // Mark the substring from i to j as a // palindrome pal[i, j] = true ; } } } } // Function to calculate the minimum number of cuts // required to make all substrings of 's' palindromic static int MinCut( string s) { if ( string .IsNullOrEmpty(s)) return 0; int n = s.Length; // 2D array to store whether substring [i, j] is a // palindrome bool [, ] pal = new bool [n, n]; GeneratePalindrome(s, pal); // Array to store minimum cuts required to make // substring [i, n-1] palindromic int [] minCutDp = new int [n]; for ( int i = 0; i < n; i++) { minCutDp[i] = int .MaxValue; } // There is no cut required for single character as // it is always a palindrome minCutDp[0] = 0; // Iterate over the given string for ( int i = 1; i < n; i++) { // Check if string 0 to i is a palindrome. Then // minCut required will be 0. if (pal[0, i]) { minCutDp[i] = 0; } else { for ( int j = i; j >= 1; j--) { // If s[i] and s[j] are equal and the // inner substring [i+1, j-1] is a // palindrome or it has a length of 1 if (pal[j, i]) { // Update the minimum cuts required // if cutting at position 'j+1' // results in a smaller value if (minCutDp[j - 1] + 1 < minCutDp[i]) minCutDp[i] = minCutDp[j - 1] + 1; } } } } // Return the minimum cuts required for the entire // string 's' return minCutDp[n - 1]; } static void Main() { string str = "ababbbabbababa" ; int cuts = MinCut(str); Console.WriteLine( "Minimum cuts required: " + cuts); } } |
Javascript
// JavaScript Code for the above approach function generatePalindrome(s, pal) { const n = s.length; // Initialize the palindrome matrix for single characters for (let i = 0; i < n; i++) { pal[i][i] = true ; } // Iterate over different lengths of substrings for (let len = 2; len <= n; len++) { // Iterate over the starting positions of substrings of current length for (let i = 0; i <= n - len; i++) { // Calculate the ending position of the substring const j = i + len - 1; // Check if the characters at the starting and ending positions are equal // and if the substring between them is a palindrome or a single character if (s[i] === s[j] && (len === 2 || pal[i + 1][j - 1])) { // Mark the substring from i to j as a palindrome pal[i][j] = true ; } } } } function minCut(s) { if (!s) return 0; const n = s.length; // 2D array to store whether substring [i, j] is a palindrome const pal = Array.from({ length: n }, () => Array(n).fill( false )); generatePalindrome(s, pal); // Array to store the minimum cuts required to make substring [i, n-1] palindromic const minCutDp = Array(n).fill(Infinity); // There is no cut required for single character as it is always a palindrome minCutDp[0] = 0; // Iterate over the given string for (let i = 1; i < n; i++) { // Check if string 0 to i is a palindrome // Then minCut required will be 0. if (pal[0][i]) { minCutDp[i] = 0; } else { for (let j = i; j >= 1; j--) { // If s[i] and s[j] are equal and the inner substring [i+1, j-1] // is a palindrome or it has a length of 1 if (pal[j][i]) { // Update the minimum cuts required if cutting at position 'j+1' results in a smaller value if (minCutDp[j - 1] + 1 < minCutDp[i]) { minCutDp[i] = minCutDp[j - 1] + 1; } } } } } // Return the minimum cuts required for the entire string 's' return minCutDp[n - 1]; } const str = "abbac" ; const cuts = minCut(str); document.write( "Minimum cuts required:" , cuts); // This code is contributed by Abhinav Mahajan (abhinav_m22) |
Minimum cuts required: 3
Time Complexity: O(n2)
Auxiliary Space: O(n2)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!