Open In App

Number of ways to divide string in sub-strings such to make them in lexicographically increasing sequence

Improve
Improve
Like Article
Like
Save
Share
Report

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:
Following are the allowed partitions: 
{“aabc”}, {“aa”, “bc”}, {“aab”, “c”}, {“a”, “abc”}, 
{“a, “ab”, “c”} and {“aa”, “b”, “c”}.

Input: S = “za” 
Output:
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)



Last Updated : 08 Mar, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads