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 partitioningint 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 codeint 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 partitioningdef 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 codes = "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 partitioningfunction 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 codevar 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!
