Count distinct original Strings
Last Updated :
28 Oct, 2023
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).
Time Complexity: O(N)
Auxiliary Space: O(N)
Similar Reads
Distinct Substring frequency counter Given a string s of length N containing only lowercase English letters and an integer K, the task is to find all distinct substrings of S of length K, and for each substring, count the number of times it occurs in S. You need to return a list of all distinct substrings along with their frequency of
4 min read
Count number of distinct substrings of a given length Given a string S of length N consisting of lower-case English alphabets and an integer 'l', find the number of distinct substrings of length 'l' of the given string. Examples: Input : s = "abcbab", l = 2 Output : 4 All distinct sub-strings of length 2 will be {"ab", "bc", "cb", "ba"} Thus, answer eq
6 min read
Count substrings made up of a single distinct character Given a string S of length N, the task is to count the number of substrings made up of a single distinct character.Note: For the repetitive occurrences of the same substring, count all repetitions. Examples: Input: str = "geeksforgeeks"Output: 15Explanation: All substrings made up of a single distin
5 min read
Count words in a given string Given a string, count the number of words in it. The words are separated by the following characters: space (' ') or new line ('\n') or tab ('\t') or a combination of these. Recommended PracticeCount number of wordsTry It!Method 1: The idea is to maintain two states: IN and OUT. The state OUT indica
15+ min read
Count of distinct substrings of a string using Suffix Trie Given a string of length n of lowercase alphabet characters, we need to count total number of distinct substrings of this string. Examples: Input : str = âababaâ Output : 10 Total number of distinct substring are 10, which are, "", "a", "b", "ab", "ba", "aba", "bab", "abab", "baba" and "ababa"Recomm
11 min read