package com.thealgorithms.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 final class PalindromicPartitioning { private 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; int j; int subLen; // different looping variables // Every substring of length 1 is a palindrome for (i = 0; i < len; i++) { isPalindrome[i][i] = true; } /* subLen is substring length. Build the solution in bottom up manner by considering all * substrings of length starting from 2 to n. */ for (subLen = 2; subLen <= len; subLen++) { // For substring of length subLen, set different possible starting indexes for (i = 0; i < len - subLen + 1; i++) { j = i + subLen - 1; // Ending index // If subLen 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 (subLen == 2) { isPalindrome[i][j] = (word.charAt(i) == word.charAt(j)); } else { isPalindrome[i][j] = (word.charAt(i) == word.charAt(j)) && isPalindrome[i + 1][j - 1]; } } } // We find the minimum for each index for (i = 0; i < len; i++) { if (isPalindrome[0][i]) { minCuts[i] = 0; } else { minCuts[i] = Integer.MAX_VALUE; for (j = 0; j < i; j++) { if (isPalindrome[j + 1][i] && 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(); } }