Given a string str. A faulty machine prints bb instead of character a and prints dd instead of char c and for the rest characters it prints normally, the task is to find how many distinct original strings could result in the given string. Since the answer can be large print ans modulo 1e9+7.
Examples:
Input: str = “gfgbbndd”
Output: 4
Explanation: Following strings result in str when the faulty machine prints it.
- gfgandd -> gfgbbndd
- gfganc -> gfgbbndd
- gfgbbnc -> gfgbbndd
- gfgbbndd -> gfgbbndd
Approach: To solve the problem follow the below idea:
We can use Dynamic Programming here, whenever we encounter double b (bb ) or double d (dd) we can generate 2 strings
- We write the recurrence relation as:
-
If we get two consecutive b or two consecutive d then
- if we take two consecutive b or consecutive d then we will have to move to index i+2
- We also have the choice to consider a single character so we include this case as well and take a single character and move to index i +1
- Else if we don’t have both the consecutive characters equal to b or d then we can simply move to index i+1 as we don’t have any choice.
- Finally, we take modulo at each step
- Edge case if the string contains ‘a’ or ‘c’ then it’s not possible.
Below is the implementation of above idea:
// C++ code for the above approach: #include <bits/stdc++.h> using namespace std;
long long mod = 1000000007;
long long solve(string& str, int & n, int index,
vector< int >& dp)
{ // Base case
if (index >= n) {
// If we reach the end then it is one
// possible string
return 1;
}
// Memoization
if (dp[index] != -1) {
return dp[index];
}
long long answer = 0;
if (str[index] == 'b' ) {
if (index + 1 < n && str[index + 1] == 'b' ) {
// If we have 2 bb then we try both
// the ways substituting single b
// with single b only
long long opt1
= solve(str, n, index + 1, dp) % mod;
// Substituting bb with a
long long opt2
= solve(str, n, index + 2, dp) % mod;
answer = (answer + opt1) % mod;
answer = (answer + opt2) % mod;
}
else {
answer = solve(str, n, index + 1, dp) % mod;
}
}
else if (str[index] == 'd' ) {
if (index + 1 < n && str[index + 1] == 'd' ) {
// If we have 2 dd then we try both
// the ways substituting single d
// with single d only
long long opt1
= solve(str, n, index + 1, dp) % mod;
// Substituting dd with c
long long opt2
= solve(str, n, index + 2, dp) % mod;
answer = (answer + opt1) % mod;
answer = (answer + opt2) % mod;
}
else {
answer = solve(str, n, index + 1, dp) % mod;
}
}
else {
// We don't have any other option so we
// call the rec with index i+1
answer = solve(str, n, index + 1, dp) % mod;
}
return dp[index] = answer % mod;
} // Drivers code int main()
{ string str;
str = "gfgbbndd" ;
int n = str.length();
bool found = false ;
for ( int i = 0; i < n; i++) {
if (str[i] == 'a' || str[i] == 'c' ) {
found = true ;
break ;
}
}
// We found character a or c which
// is not possible.
if (found == true ) {
cout << 0 << endl;
return 0;
}
// Initializing the dp vector
vector< int > dp(n, -1);
// Calling the recursion function
long long ans = solve(str, n, 0, dp);
// Priting the answer
cout << ans << endl;
return 0;
} |
// Java code for the above approach: import java.util.*;
class GFG {
static long mod = 1000000007 ;
static long solve(String str, int n, int index,
int [] dp)
{
// Base case
if (index >= n) {
// If we reach the end then it is one
// possible string
return 1 ;
}
// Memoization
if (dp[index] != - 1 ) {
return dp[index];
}
long answer = 0 ;
if (str.charAt(index) == 'b' ) {
if (index + 1 < n
&& str.charAt(index + 1 ) == 'b' ) {
// If we have 2 bb then we try both
// the ways substituting single b
// with single b only
long opt1
= solve(str, n, index + 1 , dp) % mod;
// Substituting bb with a
long opt2
= solve(str, n, index + 2 , dp) % mod;
answer = (answer + opt1) % mod;
answer = (answer + opt2) % mod;
}
else {
answer = solve(str, n, index + 1 , dp) % mod;
}
}
else if (str.charAt(index) == 'd' ) {
if (index + 1 < n
&& str.charAt(index + 1 ) == 'd' ) {
// If we have 2 dd then we try both
// the ways substituting single d
// with single d only
long opt1
= solve(str, n, index + 1 , dp) % mod;
// Substituting dd with c
long opt2
= solve(str, n, index + 2 , dp) % mod;
answer = (answer + opt1) % mod;
answer = (answer + opt2) % mod;
}
else {
answer = solve(str, n, index + 1 , dp) % mod;
}
}
else {
// We don't have any other option so we
// call the rec with index i+1
answer = solve(str, n, index + 1 , dp) % mod;
}
return dp[index] = ( int )(answer % mod);
}
// Drivers code
public static void main(String[] args)
{
String str = "gfgbbndd" ;
int n = str.length();
boolean found = false ;
for ( int i = 0 ; i < n; i++) {
if (str.charAt(i) == 'a'
|| str.charAt(i) == 'c' ) {
found = true ;
break ;
}
}
// We found character a or c which
// is not possible.
if (found == true ) {
System.out.println( 0 );
return ;
}
// Initializing the dp vector
int [] dp = new int [n];
Arrays.fill(dp, - 1 );
// Calling the recursion function
long ans = solve(str, n, 0 , dp);
// Priting the answer
System.out.println(ans);
}
} // This code is contributed by ragul21 |
mod = 1000000007
def solve( str , n, index, dp):
# Base case
if index > = n:
# If we reach the end then it is one
# possible string
return 1
# Memoization
if dp[index] ! = - 1 :
return dp[index]
answer = 0
if str [index] = = 'b' :
if index + 1 < n and str [index + 1 ] = = 'b' :
# If we have 2 bb then we try both
# the ways substituting single b
# with single b only
opt1 = solve( str , n, index + 1 , dp) % mod
# Substituting bb with a
opt2 = solve( str , n, index + 2 , dp) % mod
answer = (answer + opt1) % mod
answer = (answer + opt2) % mod
else :
answer = solve( str , n, index + 1 , dp) % mod
elif str [index] = = 'd' :
if index + 1 < n and str [index + 1 ] = = 'd' :
# If we have 2 dd then we try both
# the ways substituting single d
# with single d only
opt1 = solve( str , n, index + 1 , dp) % mod
# Substituting dd with c
opt2 = solve( str , n, index + 2 , dp) % mod
answer = (answer + opt1) % mod
answer = (answer + opt2) % mod
else :
answer = solve( str , n, index + 1 , dp) % mod
else :
# We don't have any other option so we
# call the rec with index i+1
answer = solve( str , n, index + 1 , dp) % mod
dp[index] = answer % mod
return dp[index]
# Drivers code str = "gfgbbndd"
n = len ( str )
found = False
for i in range (n):
if str [i] = = 'a' or str [i] = = 'c' :
found = True
break
if found = = True :
print ( 0 )
else :
dp = [ - 1 ] * n
ans = solve( str , n, 0 , dp)
print (ans)
|
using System;
using System.Collections.Generic;
class GFG
{ static long mod = 1000000007;
static long Solve( string str, int n, int index, List< long > dp)
{
// Base case
if (index >= n)
{
// If we reach the end, then it is one possible string
return 1;
}
// Memoization
if (dp[index] != -1)
{
return dp[index];
}
long answer = 0;
if (str[index] == 'b' )
{
if (index + 1 < n && str[index + 1] == 'b' )
{
// If we have 2 bb then we try both the ways substituting single b with single b only
long opt1 = Solve(str, n, index + 1, dp) % mod;
// Substituting bb with a
long opt2 = Solve(str, n, index + 2, dp) % mod;
answer = (answer + opt1) % mod;
answer = (answer + opt2) % mod;
}
else
{
answer = Solve(str, n, index + 1, dp) % mod;
}
}
else if (str[index] == 'd' )
{
if (index + 1 < n && str[index + 1] == 'd' )
{
// If we have 2 dd then we try both the ways substituting single d with single d only
long opt1 = Solve(str, n, index + 1, dp) % mod;
// Substituting dd with c
long opt2 = Solve(str, n, index + 2, dp) % mod;
answer = (answer + opt1) % mod;
answer = (answer + opt2) % mod;
}
else
{
answer = Solve(str, n, index + 1, dp) % mod;
}
}
else
{
// We don't have any other option so we call the recursion with index i+1
answer = Solve(str, n, index + 1, dp) % mod;
}
return dp[index] = answer % mod;
}
public static void Main( string [] args)
{
string str = "gfgbbndd" ;
int n = str.Length;
bool found = false ;
for ( int i = 0; i < n; i++)
{
if (str[i] == 'a' || str[i] == 'c' )
{
found = true ;
break ;
}
}
// We found character 'a' or 'c' which is not possible.
if (found)
{
Console.WriteLine(0);
return ;
}
// Initializing the dp list
List< long > dp = new List< long >( new long [n]);
for ( int i = 0; i < n; i++)
{
dp[i] = -1;
}
// Calling the recursion function
long ans = Solve(str, n, 0, dp);
// Printing the answer
Console.WriteLine(ans);
}
} |
// JavaScript code for the above approach const mod = 1000000007; function solve(str, index, dp) {
const n = str.length;
// Base case
if (index >= n) {
// If we reach the end, then it is one possible string
return 1;
}
// Memoization
if (dp[index] !== -1) {
return dp[index];
}
let answer = 0;
if (str[index] === 'b' ) {
if (index + 1 < n && str[index + 1] === 'b' ) {
// If we have 2 bb then we try both ways
// substituting single b with single b only
const opt1 = solve(str, index + 1, dp) % mod;
// Substituting bb with a
const opt2 = solve(str, index + 2, dp) % mod;
answer = (answer + opt1) % mod;
answer = (answer + opt2) % mod;
} else {
answer = solve(str, index + 1, dp) % mod;
}
} else if (str[index] === 'd' ) {
if (index + 1 < n && str[index + 1] === 'd' ) {
// If we have 2 dd then we try both ways
// substituting single d with single d only
const opt1 = solve(str, index + 1, dp) % mod;
// Substituting dd with c
const opt2 = solve(str, index + 2, dp) % mod;
answer = (answer + opt1) % mod;
answer = (answer + opt2) % mod;
} else {
answer = solve(str, index + 1, dp) % mod;
}
} else {
// We don't have any other option, so we call the
// recursion with index i+1
answer = solve(str, index + 1, dp) % mod;
}
return (dp[index] = answer % mod);
} function main() {
const str = "gfgbbndd" ;
const n = str.length;
let found = false ;
for (let i = 0; i < n; i++) {
if (str[i] === 'a ' || str[i] === ' c ') {
found = true;
break;
}
}
// We found character ' a ' or ' c' which is not possible.
if (found) {
console.log(0);
return ;
}
// Initializing the dp array
const dp = new Array(n).fill(-1);
// Calling the recursion function
const ans = solve(str, 0, dp);
// Printing the answer
console.log(ans);
} main(); // This code is contributed by Abhinav Mahajan (abhinav_m22). |
4
Time Complexity: O(N)
Auxiliary Space: O(N)