Given a string S, the task is to find the number of ways to divide/partition the given string in sub-strings S1, S2, S3, …, Sk such that S1 < S2 < S3 < … < Sk (Lexicographically).
Examples:
Input: S = “aabc”
Output: 6
Following are the allowed partitions:
{“aabc”}, {“aa”, “bc”}, {“aab”, “c”}, {“a”, “abc”},
{“a, “ab”, “c”} and {“aa”, “b”, “c”}.Input: S = “za”
Output: 1
Only possible partition is {“za”}.
Approach: This problem can be solved using dynamic programming.
- Define DP[i][j] as the number of ways to divide the sub-string S[0…j] such that S[i, j] is the last partition.
- Now, the recurrence relations will be DP[i][j] = Summation of (DP[k][i – 1]) for all k ? 0 and i ? N – 1 where N is the length of the string.
- Final answer will be the summation of (DP[i][N – 1]) for all i between 0 to N – 1 as these sub-strings will become the last partition in some possible way of partitioning.
- So, here for all the sub-strings S[i][j], find the sub-string S[k][i – 1] such that S[k][i – 1] is lexicographically less than S[i][j] and add DP[k][i – 1] to DP[i][j].
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; // Function to return the number of // ways of partitioning int ways(string s, int n) { int dp[n][n]; // Initialize DP table for ( int i = 0; i < n; i++) for ( int j = 0; j < n; j++) { dp[i][j] = 0; } // Base Case for ( int i = 0; i < n; i++) dp[0][i] = 1; for ( int i = 1; i < n; i++) { // To store sub-string S[i][j] string temp; for ( int j = i; j < n; j++) { temp += s[j]; // To store sub-string S[k][i-1] string test; for ( int k = i - 1; k >= 0; k--) { test += s[k]; if (test < temp) { dp[i][j] += dp[k][i - 1]; } } } } int ans = 0; for ( int i = 0; i < n; i++) { // Add all the ways where S[i][n-1] // will be the last partition ans += dp[i][n - 1]; } return ans; } // Driver code int main() { string s = "aabc" ; int n = s.length(); cout << ways(s, n); return 0; } |
Java
// Java implementation of the above approach class GFG { // Function to return the number of // ways of partitioning static int ways(String s, int n) { int dp[][] = new int [n][n]; // Initialize DP table for ( int i = 0 ; i < n; i++) for ( int j = 0 ; j < n; j++) { dp[i][j] = 0 ; } // Base Case for ( int i = 0 ; i < n; i++) dp[ 0 ][i] = 1 ; for ( int i = 1 ; i < n; i++) { // To store sub-string S[i][j] String temp = "" ; for ( int j = i; j < n; j++) { temp += s.charAt(j); // To store sub-string S[k][i-1] String test = "" ; for ( int k = i - 1 ; k >= 0 ; k--) { test += s.charAt(k); if (test.compareTo(temp) < 0 ) { dp[i][j] += dp[k][i - 1 ]; } } } } int ans = 0 ; for ( int i = 0 ; i < n; i++) { // Add all the ways where S[i][n-1] // will be the last partition ans += dp[i][n - 1 ]; } return ans; } // Driver code public static void main (String[] args) { String s = "aabc" ; int n = s.length(); System.out.println(ways(s, n)); } } // This code is contributed by AnkitRai01 |
Python3
# Python3 implementation of the approach # Function to return the number of # ways of partitioning def ways(s, n): dp = [[ 0 for i in range (n)] for i in range (n)] # Base Case for i in range (n): dp[ 0 ][i] = 1 for i in range ( 1 , n): # To store sub-S[i][j] temp = "" for j in range (i, n): temp + = s[j] # To store sub-S[k][i-1] test = "" for k in range (i - 1 , - 1 , - 1 ): test + = s[k] if (test < temp): dp[i][j] + = dp[k][i - 1 ] ans = 0 for i in range (n): # Add all the ways where S[i][n-1] # will be the last partition ans + = dp[i][n - 1 ] return ans # Driver code s = "aabc" n = len (s) print (ways(s, n)) # This code is contributed by Mohit Kumarv |
C#
// C# implementation of the above approach using System; class GFG { // Function to return the number of // ways of partitioning static int ways(String s, int n) { int [,]dp = new int [n, n]; // Initialize DP table for ( int i = 0; i < n; i++) for ( int j = 0; j < n; j++) { dp[i, j] = 0; } // Base Case for ( int i = 0; i < n; i++) dp[0, i] = 1; for ( int i = 1; i < n; i++) { // To store sub-string S[i,j] String temp = "" ; for ( int j = i; j < n; j++) { temp += s[j]; // To store sub-string S[k,i-1] String test = "" ; for ( int k = i - 1; k >= 0; k--) { test += s[k]; if (test.CompareTo(temp) < 0) { dp[i, j] += dp[k, i - 1]; } } } } int ans = 0; for ( int i = 0; i < n; i++) { // Add all the ways where S[i,n-1] // will be the last partition ans += dp[i, n - 1]; } return ans; } // Driver code public static void Main (String[] args) { String s = "aabc" ; int n = s.Length; Console.WriteLine(ways(s, n)); } } // This code is contributed by PrinciRaj1992 |
Javascript
<script> // Javascript implementation of the approach // Function to return the number of // ways of partitioning function ways(s, n) { var dp = Array.from(Array(n), ()=> Array(n).fill(0)); // Base Case for ( var i = 0; i < n; i++) dp[0][i] = 1; for ( var i = 1; i < n; i++) { // To store sub-string S[i][j] var temp; for ( var j = i; j < n; j++) { temp += s[j]; // To store sub-string S[k][i-1] var test; for ( var k = i - 1; k >= 0; k--) { test += s[k]; if (test < temp) { dp[i][j] += dp[k][i - 1]; } } } } var ans = 0; for ( var i = 0; i < n; i++) { // Add all the ways where S[i][n-1] // will be the last partition ans += dp[i][n - 1]; } return ans; } // Driver code var s = "aabc" ; var n = s.length; document.write( ways(s, n)); // This code is contributed by itsok. </script> |
6
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!