package DynamicProgramming; import java.util.Scanner; /** * @file * @brief Implements [Palindrome * Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) * algorithm, giving you the minimum number of partitions you need to make * * @details * palindrome partitioning uses dynamic programming and goes to all the possible * partitions to find the minimum you are given a string and you need to give * minimum number of partitions needed to divide it into a number of palindromes * [Palindrome Partitioning] * (https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/) overall time * complexity O(n^2) For example: example 1:- String : "nitik" Output : 2 => "n * | iti | k" For example: example 2:- String : "ababbbabbababa" Output : 3 => * "aba | b | bbabb | ababa" * @author [Syed] (https://github.com/roeticvampire) */ public class PalindromicPartitioning { public static int minimalpartitions(String word){ int len=word.length(); /* We Make two arrays to create a bottom-up solution. minCuts[i] = Minimum number of cuts needed for palindrome partitioning of substring word[0..i] isPalindrome[i][j] = true if substring str[i..j] is palindrome Base Condition: C[i] is 0 if P[0][i]= true */ int[] minCuts = new int[len]; boolean[][] isPalindrome = new boolean[len][len]; int i, j, L; // different looping variables // Every substring of length 1 is a palindrome for (i = 0; i < len; i++) { isPalindrome[i][i] = true; } /* L is substring length. Build the solution in bottom up manner by considering all substrings of length starting from 2 to n. */ for (L = 2; L <= len; L++) { // For substring of length L, set different possible starting indexes for (i = 0; i < len - L + 1; i++) { j = i + L - 1; // 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) isPalindrome[i][j] = (word.charAt(i) == word.charAt(j)); else { if((word.charAt(i) == word.charAt(j)) && isPalindrome[i + 1][j - 1]) isPalindrome[i][j] =true; else isPalindrome[i][j]=false; } } } //We find the minimum for each index for (i = 0; i < len; i++) { if (isPalindrome[0][i] == true) minCuts[i] = 0; else { minCuts[i] = Integer.MAX_VALUE; for (j = 0; j < i; j++) { if (isPalindrome[j + 1][i] == true && 1 + minCuts[j] < minCuts[i]) minCuts[i] = 1 + minCuts[j]; } } } // Return the min cut value for complete // string. i.e., str[0..n-1] return minCuts[len - 1]; } public static void main(String[] args) { Scanner input = new Scanner(System.in); String word; System.out.println("Enter the First String"); word = input.nextLine(); // ans stores the final minimal cut count needed for partitioning int ans = minimalpartitions(word); System.out.println( "The minimum cuts needed to partition \"" + word + "\" into palindromes is " + ans); input.close(); } }