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: 139Input: 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++ 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;
} |
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 |
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 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)); |
# 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))
|
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++ 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;
} |
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# 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 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 |
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. |
663818944
Time Complexity: O(N)
Auxiliary Space: O(N*K1*K2)