Open In App

Count distinct original Strings

Last Updated : 28 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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++




// 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




// 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


Python3




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)


C#




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




// 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).


Output

4








Time Complexity: O(N)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads