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> |
Output:
6
Time Complexity: O(n2)
Auxiliary Space: O(n2)