Open In App

Count valid strings that contains ‘0’, ‘1’ or ‘2’

Last Updated : 04 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an integer n(1 <= n <= 105), the task is to count valid string S of length n, which contains characters ‘0’, ‘1’, or ‘2’ only. For a valid string, it must follow the below conditions.

  • There should not be more than K1 occurrences of ‘0’.
  • There should not be more than K2 consecutive ‘1’s. (1 <= K1, K2 <= 10)

Note: The answer may be very large, so return it modulo 109 + 7.

Examples:

Input: n = 2, K1 = 1, K2 = 2
Output: 8
Explanation: There are 8 valid strings of length 2: “22”, “02”, “20”, “12”, “21”, “01”, “10”, “11”. “00” is not valid string because there should not be more than one occurrence of ‘0’.

Input: n = 5, K1 = 2, K2 = 3;
Output: 139

Input: n = n = 1012, K1 = 3, K2 = 5
Output: 663818944

Counting valid strings that contain ‘0’, ‘1’, or ‘2’ using Recursion:

  • Base Case: When n becomes 0, this indicates that a valid string of the desired length has been generated. So, return 1.
  • Within the countValidString() function, iterates over the three possible characters: ‘0’, ‘1’, and ‘2’. For each character, checks if it can be added to the string based on the constraints:
    • If zeroCount < K1, we can add ‘0’ to the string. So, recur for rest of the length and store result in res1.
    • If oneCount < K2, we can add ‘1’ to the string. So, recur for rest of the length and store result in res2.
    • We can always add ‘2’ to the string. So, recur for rest of the length and store result in res3.
  • Finally, return the overall result = (res1 + res2 + res3) % 1e9+7.

Below is the implementation of the above approach:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
// Define a modulo value
int mod = 1e9 + 7;
 
// Recursive function to calculate the number
// of valid strings
int countValidString(int zeroCount, int oneCount, int K1,
                     int K2, int n)
{
 
    // Base case: If n becomes 0, return 1
    // as a valid record is found
    if (n == 0)
        return 1;
 
    // Initialize variables to store
    // different results
    long long res1 = 0, res2 = 0, res3 = 0;
 
    // Iterate over three possible
    // characters: 0, 1, and 2
    for (int i = 0; i <= 2; i++) {
 
        // Check if we can add '0' to
        // the string (zeroCount < K1)
        if (zeroCount < K1 && i == 0) {
            res1 = countValidString(zeroCount + 1, 0, K1,
                                    K2, n - 1);
        }
 
        // Check if we can add '1' to the
        // string (oneCount < K2)
        if (oneCount < K2 && i == 1) {
            res2 = countValidString(zeroCount, oneCount + 1,
                                    K1, K2, n - 1);
        }
 
        // Add '2' to the string
        res3
            = countValidString(zeroCount, 0, K1, K2, n - 1);
    }
 
    // Return the sum modulo 'mod'
    return (res1 + res2 + res3) % mod;
}
 
// Drivers code
int main()
{
    int n = 2, K1 = 1, K2 = 2;
 
    // Call the solve function to calculate
    // the valid strings
    cout << countValidString(0, 0, K1, K2, n);
 
    return 0;
}


Java




public class ValidStrings {
    // Define a modulo value
    static int mod = (int) 1e9 + 7;
 
    // Recursive function to calculate the number
    // of valid strings
    static long countValidString(int zeroCount, int oneCount, int K1, int K2, int n) {
        // Base case: If n becomes 0, return 1
        // as a valid record is found
        if (n == 0)
            return 1;
 
        // Initialize variables to store different results
        long res1 = 0, res2 = 0, res3 = 0;
 
        // Iterate over three possible characters: 0, 1, and 2
        for (int i = 0; i <= 2; i++) {
            // Check if we can add '0' to the string (zeroCount < K1)
            if (zeroCount < K1 && i == 0) {
                res1 = countValidString(zeroCount + 1, 0, K1, K2, n - 1);
            }
 
            // Check if we can add '1' to the string (oneCount < K2)
            if (oneCount < K2 && i == 1) {
                res2 = countValidString(zeroCount, oneCount + 1, K1, K2, n - 1);
            }
 
            // Add '2' to the string
            res3 = countValidString(zeroCount, 0, K1, K2, n - 1);
        }
 
        // Return the sum modulo 'mod'
        return (res1 + res2 + res3) % mod;
    }
 
    // Driver code
    public static void main(String[] args) {
        int n = 2, K1 = 1, K2 = 2;
 
        // Call the countValidString function to calculate the valid strings
        System.out.println(countValidString(0, 0, K1, K2, n));
    }
}
//Contributed by Aditi Tyagi


C#




using System;
 
class Program
{
    // Define a modulo value
    const int mod = 1000000007;
 
    // Recursive function to calculate the number
    // of valid strings
    static long CountValidString(int zeroCount, int oneCount, int K1, int K2, int n)
    {
        // Base case: If n becomes 0, return 1
        // as a valid record is found
        if (n == 0)
            return 1;
 
        // Initialize variables to store different results
        long res1 = 0, res2 = 0, res3 = 0;
 
        // Iterate over three possible characters: 0, 1, and 2
        for (int i = 0; i <= 2; i++)
        {
            // Check if we can add '0' to the string (zeroCount < K1)
            if (zeroCount < K1 && i == 0)
            {
                res1 = CountValidString(zeroCount + 1, 0, K1, K2, n - 1);
            }
 
            // Check if we can add '1' to the string (oneCount < K2)
            if (oneCount < K2 && i == 1)
            {
                res2 = CountValidString(zeroCount, oneCount + 1, K1, K2, n - 1);
            }
 
            // Add '2' to the string
            res3 = CountValidString(zeroCount, 0, K1, K2, n - 1);
        }
 
        // Return the sum modulo 'mod'
        return (res1 + res2 + res3) % mod;
    }
 
    // Driver code
    static void Main()
    {
        int n = 2, K1 = 1, K2 = 2;
 
        // Call the CountValidString function to calculate the valid strings
        Console.WriteLine(CountValidString(0, 0, K1, K2, n));
    }
}


Javascript




// JavaScript code for the above approach:
 
// Define a modulo value
const mod = 1e9 + 7;
 
// Recursive function to calculate the number
// of valid strings
function countValidString(zeroCount, oneCount, K1, K2, n) {
    // Base case: If n becomes 0, return 1
    // as a valid record is found
    if (n === 0) {
        return 1;
    }
 
    // Initialize variables to store
    // different results
    let res1 = 0,
    res2 = 0,
    res3 = 0;
 
    // Iterate over three possible
    // characters: 0, 1, and 2
    for (let i = 0; i <= 2; i++) {
        // Check if we can add '0' to
        // the string (zeroCount < K1)
        if (zeroCount < K1 && i === 0) {
            res1 = countValidString(zeroCount + 1, 0, K1, K2, n - 1);
        }
 
        // Check if we can add '1' to the
        // string (oneCount < K2)
        if (oneCount < K2 && i === 1) {
            res2 = countValidString(zeroCount, oneCount + 1, K1, K2, n - 1);
        }
 
        // Add '2' to the string
        res3 = countValidString(zeroCount, 0, K1, K2, n - 1);
    }
 
    // Return the sum modulo 'mod'
    return (res1 + res2 + res3) % mod;
}
 
// Drivers code
 
const n = 2,
K1 = 1,
K2 = 2;
 
// Call the solve function to calculate
// the valid strings
console.log(countValidString(0, 0, K1, K2, n));


Python3




# Define a modulo value
mod = 10**9 + 7
 
# Recursive function to calculate the number
# of valid strings
 
 
def countValidString(zeroCount, oneCount, K1, K2, n):
 
    # Base case: If n becomes 0, return 1
    # as a valid record is found
    if n == 0:
        return 1
 
    # Initialize variables to store
    # different results
    res1 = 0
    res2 = 0
    res3 = 0
 
    # Iterate over three possible
    # characters: 0, 1, and 2
    for i in range(3):
 
        # Check if we can add '0' to
        # the string (zeroCount < K1)
        if zeroCount < K1 and i == 0:
            res1 = countValidString(zeroCount + 1, 0, K1, K2, n - 1)
 
        # Check if we can add '1' to the
        # string (oneCount < K2)
        if oneCount < K2 and i == 1:
            res2 = countValidString(zeroCount, oneCount + 1, K1, K2, n - 1)
 
        # Add '2' to the string
        res3 = countValidString(zeroCount, 0, K1, K2, n - 1)
 
    # Return the sum modulo 'mod'
    return (res1 + res2 + res3) % mod
 
 
# Drivers code
if __name__ == "__main__":
    n = 2
    K1 = 1
    K2 = 2
 
    # Call the solve function to calculate
    # the valid strings
    print(countValidString(0, 0, K1, K2, n))


Output

8


Time Complexity: O(3^n), where ‘n’ is the length of the string.
Auxiliary Space: O(n)

Counting valid strings that contains ‘0’, ‘1’, or ‘2’ using Dynamic Programming (Memoization):

Explore the valid string using recursion and memoize the subproblems. The state includes the counts of ‘0’s and consecutive ‘1’s, and recursion explores character choices (‘0’, ‘1’, ‘2’) for valid strings, we also keep maintain the constraints like no more than K1 ‘0’ and no K2 consecutive ‘1’s. Finally, add valid answers to result and return the result by taking modulo.

Step-by-step approach:

  • Use a three dimensional dp[zeroCount][oneCount][n1], which represents the result of subproblem when the count of zero was zeroCount, the count of one was oneCount for n1 length string.
  • Base Case: When n becomes 0, this indicates that a valid string of the desired length has been generated. So, return 1.
  • Within the countValidString() function, iterates over the three possible characters: ‘0’, ‘1’, and ‘2’. For each character, checks if it can be added to the string based on the constraints:
    • If zeroCount < K1, we can add ‘0’ to the string. So, recur for rest of the length and store result in res1.
    • If oneCount < K2, we can add ‘1’ to the string. So, recur for rest of the length and store result in res2.
    • We can always add ‘2’ to the string. So, recur for rest of the length and store result in res3.
  • Finally, store the overall result in dp before returning result = (res1 + res2 + res3) % 1e9+7.

Below is the implementation of the above approch:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
// Define a 3D array for memoization
int dp[10][10][100005];
 
// Define a modulo value
int mod = 1e9 + 7;
 
// Recursive function to calculate the
// number of valid strings
int countValidString(int zeroCount, int oneCount, int K1,
                    int K2, int n)
{
 
    // Base case: If n becomes 0, return 1
    // as a valid record is found
    if (n == 0)
        return 1;
 
    // If the result for the current state
    // is already calculated, return it
    if (dp[zeroCount][oneCount][n] != -1)
        return dp[zeroCount][oneCount][n];
 
    // Initialize variables to
    // store different results
    long long res1 = 0, res2 = 0, res3 = 0;
 
    // Iterate over three possible
    // characters: 0, 1, and 2
    for (int i = 0; i <= 2; i++) {
 
        // Check if we can add '0' to
        // the string (zeroCount < K1)
        if (zeroCount < K1 && i == 0) {
            res1 = countValidString(zeroCount + 1, 0, K1,
                                    K2, n - 1);
        }
 
        // Check if we can add '1' to the
        // string (oneCount < K2)
        if (oneCount < K2 && i == 1) {
            res2 = countValidString(zeroCount, oneCount + 1,
                                    K1, K2, n - 1);
        }
 
        // Add '2' to the string
        res3
            = countValidString(zeroCount, 0, K1, K2, n - 1);
    }
 
    // Store the result in the memoization
    // table and return the sum modulo 'mod'
    return dp[zeroCount][oneCount][n]
        = (res1 + res2 + res3) % mod;
}
 
// Drivers code
int main()
{
    int n = 1012, K1 = 3, K2 = 5;
 
    // Initialize the memoization table with -1
    memset(dp, -1, sizeof(dp));
 
    // Call the solve function to calculate
    // the valid strings
    cout << countValidString(0, 0, K1, K2, n);
 
    return 0;
}


Java




import java.util.Arrays;
 
public class ValidStrings {
 
    // Define a 3D array for memoization
    static long[][][] dp = new long[10][10][100005];
 
    // Define a modulo value
    static int mod = (int) 1e9 + 7;
 
    // Recursive function to calculate the number of valid strings
    static long countValidString(int zeroCount, int oneCount, int K1, int K2, int n) {
 
        // Base case: If n becomes 0, return 1 as a valid record is found
        if (n == 0)
            return 1;
 
        // If the result for the current state is already calculated, return it
        if (dp[zeroCount][oneCount][n] != -1)
            return dp[zeroCount][oneCount][n];
 
        // Initialize variables to store different results
        long res1 = 0, res2 = 0, res3 = 0;
 
        // Iterate over three possible characters: 0, 1, and 2
        for (int i = 0; i <= 2; i++) {
 
            // Check if we can add '0' to the string (zeroCount < K1)
            if (zeroCount < K1 && i == 0) {
                res1 = countValidString(zeroCount + 1, 0, K1, K2, n - 1);
            }
 
            // Check if we can add '1' to the string (oneCount < K2)
            if (oneCount < K2 && i == 1) {
                res2 = countValidString(zeroCount, oneCount + 1, K1, K2, n - 1);
            }
 
            // Add '2' to the string
            res3 = countValidString(zeroCount, 0, K1, K2, n - 1);
        }
 
        // Store the result in the memoization table and return the sum modulo 'mod'
        return dp[zeroCount][oneCount][n] = (res1 + res2 + res3) % mod;
    }
 
    // Main method
    public static void main(String[] args) {
        int n = 1012, K1 = 3, K2 = 5;
 
        // Initialize the memoization table with -1
        for (long[][] row1 : dp) {
            for (long[] row2 : row1) {
                Arrays.fill(row2, -1);
            }
        }
 
        // Call the function to calculate the valid strings
        System.out.println(countValidString(0, 0, K1, K2, n));
    }
}


C#




// C# program for the above approach
using System;
 
public class ValidStrings {
    // Define a 3D array for memoization
    static long[, , ] dp = new long[10, 10, 100005];
 
    // Define a modulo value
    static int mod = (int)1e9 + 7;
 
    // Recursive function to calculate the number of valid
    // strings
    static long CountValidString(int zeroCount,
                                 int oneCount, int K1,
                                 int K2, int n)
    {
        // Base case: If n becomes 0, return 1 as a valid
        // record is found
        if (n == 0)
            return 1;
 
        // If the result for the current state is already
        // calculated, return it
        if (dp[zeroCount, oneCount, n] != -1)
            return dp[zeroCount, oneCount, n];
 
        // Initialize variables to store different results
        long res1 = 0, res2 = 0, res3 = 0;
 
        // Iterate over three possible characters: 0, 1, and
        // 2
        for (int i = 0; i <= 2; i++) {
            // Check if we can add '0' to the string
            // (zeroCount < K1)
            if (zeroCount < K1 && i == 0) {
                res1 = CountValidString(zeroCount + 1, 0,
                                        K1, K2, n - 1);
            }
 
            // Check if we can add '1' to the string
            // (oneCount < K2)
            if (oneCount < K2 && i == 1) {
                res2 = CountValidString(
                    zeroCount, oneCount + 1, K1, K2, n - 1);
            }
 
            // Add '2' to the string
            res3 = CountValidString(zeroCount, 0, K1, K2,
                                    n - 1);
        }
 
        // Store the result in the memoization table and
        // return the sum modulo 'mod'
        return dp[zeroCount, oneCount, n]
            = (res1 + res2 + res3) % mod;
    }
 
    // Main method
    public static void Main(string[] args)
    {
        int n = 1012, K1 = 3, K2 = 5;
 
        // Initialize the memoization table with -1
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                for (int k = 0; k < 100005; k++) {
                    dp[i, j, k] = -1;
                }
            }
        }
 
        // Call the function to calculate the valid strings
        Console.WriteLine(
            CountValidString(0, 0, K1, K2, n));
    }
}
 
// This code is contributed by Susobhan Akhuli


Javascript




// Javascript program for the above approach
// Define a 3D array for memoization
const dp = Array.from({ length: 10 }, () =>
  Array.from({ length: 10 }, () => Array(100005).fill(-1))
);
 
// Define a modulo value
const mod = 1e9 + 7;
 
// Recursive function to calculate the number of valid strings
function countValidString(zeroCount, oneCount, K1, K2, n) {
  // Base case: If n becomes 0, return 1 as a valid record is found
  if (n === 0) return 1;
 
  // If the result for the current state is already calculated, return it
  if (dp[zeroCount][oneCount][n] !== -1) return dp[zeroCount][oneCount][n];
 
  // Initialize variables to store different results
  let res1 = 0,
    res2 = 0,
    res3 = 0;
 
  // Iterate over three possible characters: 0, 1, and 2
  for (let i = 0; i <= 2; i++) {
    // Check if we can add '0' to the string (zeroCount < K1)
    if (zeroCount < K1 && i === 0) {
      res1 = countValidString(zeroCount + 1, 0, K1, K2, n - 1);
    }
 
    // Check if we can add '1' to the string (oneCount < K2)
    if (oneCount < K2 && i === 1) {
      res2 = countValidString(zeroCount, oneCount + 1, K1, K2, n - 1);
    }
 
    // Add '2' to the string
    res3 = countValidString(zeroCount, 0, K1, K2, n - 1);
  }
 
  // Store the result in the memoization table and return the sum modulo 'mod'
  return (dp[zeroCount][oneCount][n] = (res1 + res2 + res3) % mod);
}
 
const n = 1012,
K1 = 3,
K2 = 5;
 
// Initialize the memoization table with -1
dp.forEach((row1) => {
row1.forEach((row2) => {
  row2.fill(-1);
});
});
 
// Call the function to calculate the valid strings
console.log(countValidString(0, 0, K1, K2, n));
 
// This code is contributed by Susobhan Akhuli


Python3




import sys
 
# Increase recursion limit to avoid RecursionError
sys.setrecursionlimit(10**6)
 
# Define a 3D array for memoization
dp = [[[None for _ in range(100005)] for _ in range(10)] for _ in range(10)]
 
# Define a modulo value
mod = int(1e9 + 7)
 
# Recursive function to calculate the number of valid strings
def count_valid_string(zero_count, one_count, K1, K2, n):
    # Base case: If n becomes 0, return 1 as a valid record is found
    if n == 0:
        return 1
 
    # If the result for the current state is already calculated, return it
    if dp[zero_count][one_count][n] is not None:
        return dp[zero_count][one_count][n]
 
    # Initialize variables to store different results
    res1, res2, res3 = 0, 0, 0
 
    # Iterate over three possible characters: 0, 1, and 2
    for i in range(3):
        # Check if we can add '0' to the string (zero_count < K1)
        if zero_count < K1 and i == 0:
            res1 = count_valid_string(zero_count + 1, 0, K1, K2, n - 1)
 
        # Check if we can add '1' to the string (one_count < K2)
        if one_count < K2 and i == 1:
            res2 = count_valid_string(zero_count, one_count + 1, K1, K2, n - 1)
 
        # Add '2' to the string
        res3 = count_valid_string(zero_count, 0, K1, K2, n - 1)
 
    # Store the result in the memoization table and return the sum modulo 'mod'
    dp[zero_count][one_count][n] = (res1 + res2 + res3) % mod
    return dp[zero_count][one_count][n]
 
# Drivers code
def main():
    n, K1, K2 = 1012, 3, 5
 
    # Initialize the memoization table with None
    for i in range(10):
        for j in range(10):
            dp[i][j] = [None] * 100005
 
    # Call the function to calculate the valid strings
    print(count_valid_string(0, 0, K1, K2, n))
 
if __name__ == "__main__":
    main()
#this code is contributed by Aman.


Output

663818944












Time Complexity: O(N)
Auxiliary Space: O(N*K1*K2)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads