Count possible decoding of a given digit sequence with hidden characters
Last Updated :
09 May, 2022
Given a string S containing digits and character ‘*’ i.e. hidden character, the task is to find the number of ways to decode this hidden character of the given string.
Since the answer may be very large, return it modulo 109+7.
A string containing letters from A-Z can be encoded into numbers using the following mapping:
‘A’ -> “1”
‘B’ -> “2”
‘C’ -> “3”
‘D’ -> “4”
…
…
‘Z’ -> “26”
Note: Characters including 0 are not included in the problem like (J ? 10).
Examples:
Input: s = “*”
Output: 9
Explanation: The encoded message can represent any of the encoded messages “1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, or “9”.
Each of these can be decoded to the strings “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, and “I” respectively.
Hence, there are a total of 9 ways to decode “*”.
Input: s = “1*”
Output: 18
Explanation: The encoded message can represent any of the encoded messages “11”, “12”, “13”, “14”, “15”, “16”, “17”, “18”, or “19”.
Each of these encoded messages have 2 ways to be decoded (e.g. “11” can be decoded to “AA” or “K”).
Hence, there are a total of 9 × 2 = 18 ways to decode “1*”.
Approach:
This problem can be solved by observing that any constant number can be either decoded in a character which is a single-digit number or it can be decoded into a double-digit number if (i-1)th character is ‘1’ or (i-1)th character is ‘2’ and ith character is between 1 and 6. Therefore, the current state depends on the previous state, and dynamic programming can be used to solve the problem. Follow the steps below to solve the problem:
1. Let dp[i] represent the number of ways to decode the string characters from 0 to i.
2. If the ith character is ‘*’ :
- dp[i] = dp[i-1]*9 considering ‘*’ can be 1 to 9, and it is considered alone as a character.
- Now, if the i and i-1 characters are combined, then,
- If (i-1)th character is ‘*’ then the two “**” together can form 15 possible characters(like 13 will form character ‘M’), so we add 15×dp[i-2] to dp[i].
- If (i-1)th character is ‘1’ then dp[i] = dp[i] + 9×dp[i-2] because the possible characters that can be decoded will be 11 to 19(K to S).
- If (i-1)th character is ‘2’ then dp[i] = dp[i] + 6×dp[i-2] as it can take value from 21 to 26.
3. If the ith character is not ‘*’:
- dp[i] = dp[i] + dp[i-1] considering ith character alone as a number.
- Now, if it is possible to combine (i-1)th character and ith character together then add dp[i-2] to dp[i].
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int M = 1000000007;
int waysOfDecoding(string s)
{
vector< int > dp(( int )s.size()+1);
dp[0] = 1;
dp[1] = s[0] == '*'
? 9
: s[0] == '0' ? 0 : 1;
for ( int i = 1; i < ( int )s.size(); i++) {
if (s[i] == '*' ) {
dp[i + 1] = 9 * dp[i];
if (s[i - 1] == '1' )
dp[i + 1]
= (dp[i + 1] + 9 * dp[i - 1]) % M;
else if (s[i - 1] == '2' )
dp[i + 1]
= (dp[i + 1] + 6 * dp[i - 1]) % M;
else if (s[i - 1] == '*' )
dp[i + 1]
= (dp[i + 1] + 15 * dp[i - 1]) % M;
}
else {
dp[i + 1] = s[i] != '0' ? dp[i] : 0;
if (s[i - 1] == '1' )
dp[i + 1]
= (dp[i + 1] + dp[i - 1])
% M;
else if (s[i - 1] == '2'
&& s[i] <= '6' )
dp[i + 1]
= (dp[i + 1] + dp[i - 1]) % M;
else if (s[i - 1] == '*' )
dp[i + 1]
= (dp[i + 1]
+ (s[i] <= '6' ? 2 : 1)
* dp[i - 1])
% M;
}
}
return dp[( int )s.size()];
}
int main()
{
string s = "12" ;
cout<<waysOfDecoding(s);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int M = 1000000007 ;
static int waysOfDecoding(String s)
{
long [] dp = new long [s.length() + 1 ];
dp[ 0 ] = 1 ;
dp[ 1 ] = s.charAt( 0 ) == '*'
? 9
: s.charAt( 0 ) == '0' ? 0 : 1 ;
for ( int i = 1 ; i < s.length(); i++) {
if (s.charAt(i) == '*' ) {
dp[i + 1 ] = 9 * dp[i];
if (s.charAt(i - 1 ) == '1' )
dp[i + 1 ]
= (dp[i + 1 ] + 9 * dp[i - 1 ]) % M;
else if (s.charAt(i - 1 ) == '2' )
dp[i + 1 ]
= (dp[i + 1 ] + 6 * dp[i - 1 ]) % M;
else if (s.charAt(i - 1 ) == '*' )
dp[i + 1 ]
= (dp[i + 1 ] + 15 * dp[i - 1 ]) % M;
}
else {
dp[i + 1 ] = s.charAt(i) != '0' ? dp[i] : 0 ;
if (s.charAt(i - 1 ) == '1' )
dp[i + 1 ]
= (dp[i + 1 ] + dp[i - 1 ])
% M;
else if (s.charAt(i - 1 ) == '2'
&& s.charAt(i) <= '6' )
dp[i + 1 ]
= (dp[i + 1 ] + dp[i - 1 ]) % M;
else if (s.charAt(i - 1 ) == '*' )
dp[i + 1 ]
= (dp[i + 1 ]
+ (s.charAt(i) <= '6' ? 2 : 1 )
* dp[i - 1 ])
% M;
}
}
return ( int )dp[s.length()];
}
public static void main(String[] args)
{
String s = "12" ;
System.out.println(waysOfDecoding(s));
}
}
|
Python3
M = 1000000007
def waysOfDecoding(s):
dp = [ 0 ] * ( len (s) + 1 )
dp[ 0 ] = 1
if s[ 0 ] = = '*' :
dp[ 1 ] = 9
elif s[ 0 ] = = '0' :
dp[ 1 ] = 0
else :
dp[ 1 ] = 1
for i in range ( len (s)):
if (s[i] = = '*' ):
dp[i + 1 ] = 9 * dp[i]
if (s[i - 1 ] = = '1' ):
dp[i + 1 ] = (dp[i + 1 ] + 9 * dp[i - 1 ]) % M
elif (s[i - 1 ] = = '2' ):
dp[i + 1 ] = (dp[i + 1 ] + 6 * dp[i - 1 ]) % M
elif (s[i - 1 ] = = '*' ):
dp[i + 1 ] = (dp[i + 1 ] + 15 * dp[i - 1 ]) % M
else :
if s[i] ! = '0' :
dp[i + 1 ] = dp[i]
else :
dp[i + 1 ] = 0
if (s[i - 1 ] = = '1' ):
dp[i + 1 ] = (dp[i + 1 ] + dp[i - 1 ]) % M
elif (s[i - 1 ] = = '2'
and s[i] < = '6' ):
dp[i + 1 ] = (dp[i + 1 ] + dp[i - 1 ]) % M
elif (s[i - 1 ] = = '*' ):
if (s[i] < = '6' ):
dp[i + 1 ] = dp[i + 1 ] + 2 * dp[i - 1 ]
else :
dp[i + 1 ] = dp[i + 1 ] + 1 * dp[i - 1 ]
dp[i + 1 ] = dp[i + 1 ] % M
return dp[ len (s)]
if __name__ = = "__main__" :
s = "12"
print (waysOfDecoding(s))
|
C#
using System;
class GFG{
static int M = 1000000007;
static int waysOfDecoding(String s)
{
long [] dp = new long [s.Length + 1];
dp[0] = 1;
dp[1] = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
for ( int i = 1; i < s.Length; i++)
{
if (s[i] == '*' )
{
dp[i + 1] = 9 * dp[i];
if (s[i - 1] == '1' )
dp[i + 1] = (dp[i + 1] + 9 *
dp[i - 1]) % M;
else if (s[i - 1] == '2' )
dp[i + 1] = (dp[i + 1] + 6 *
dp[i - 1]) % M;
else if (s[i - 1] == '*' )
dp[i + 1] = (dp[i + 1] + 15 *
dp[i - 1]) % M;
}
else
{
dp[i + 1] = s[i] != '0' ? dp[i] : 0;
if (s[i - 1] == '1' )
dp[i + 1] = (dp[i + 1] + dp[i - 1]) % M;
else if (s[i - 1] == '2' && s[i] <= '6' )
dp[i + 1] = (dp[i + 1] + dp[i - 1]) % M;
else if (s[i - 1] == '*' )
dp[i + 1] = (dp[i + 1] + (s[i] <= '6' ? 2 : 1) *
dp[i - 1]) % M;
}
}
return ( int )dp[s.Length];
}
public static void Main()
{
String s = "12" ;
Console.WriteLine(waysOfDecoding(s));
}
}
|
Javascript
<script>
let M = 1000000007;
function waysOfDecoding(s)
{
let dp = new Array(s.length + 1);
for (let i=0;i<s.length+1;i++)
dp[i] = 0;
dp[0] = 1;
dp[1] = s[0] == '*'
? 9
: s[0] == '0' ? 0 : 1;
for (let i = 1; i < s.length; i++) {
if (s[i] == '*' ) {
dp[i + 1] = 9 * dp[i];
if (s[i-1] == '1' )
dp[i + 1]
= (dp[i + 1] + 9 * dp[i - 1]) % M;
else if (s[i-1] == '2' )
dp[i + 1]
= (dp[i + 1] + 6 * dp[i - 1]) % M;
else if (s[i-1] == '*' )
dp[i + 1]
= (dp[i + 1] + 15 * dp[i - 1]) % M;
}
else {
dp[i + 1] = s[i] != '0' ? dp[i] : 0;
if (s[i-1] == '1' )
dp[i + 1]
= (dp[i + 1] + dp[i - 1])
% M;
else if (s[i-1] == '2'
&& s[i] <= '6' )
dp[i + 1]
= (dp[i + 1] + dp[i - 1]) % M;
else if (s[i-1] == '*' )
dp[i + 1]
= (dp[i + 1]
+ (s[i] <= '6' ? 2 : 1)
* dp[i - 1])
% M;
}
}
return dp[s.length];
}
let s = "12" ;
document.write(waysOfDecoding(s));
</script>
|
Time complexity: O(n)
Auxiliary Space: O(n)
Further optimization of space
If the above code is observed carefully, it is observed that the value of dp[i] is found using dp[i-1] and dp[i-2]. So to optimize the space further, instead of creating an array of dp of length N, we can use three variables – second(stores the value of dp[i]), first(stores the value of dp[i-2]), and temp(stores the value of dp[i-1]). So after finding the value of the second(dp[i]), modify first = temp and temp = second and then calculate the value again of second(dp[i]) using the variable first and temp.
C++
#include <bits/stdc++.h>
using namespace std;
int M = 1000000007;
int waysOfDecoding(string s)
{
long first = 1,
second = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
for ( int i = 1; i < s.size(); i++)
{
long temp = second;
if (s[i] == '*' )
{
second = 9 * second;
if (s[i - 1] == '1' )
second = (second + 9 * first) % M;
else if (s[i - 1] == '2' )
second = (second + 6 * first) % M;
else if (s[i - 1] == '*' )
second = (second + 15 * first) % M;
}
else
{
second = s[i] != '0' ? second : 0;
if (s[i - 1] == '1' )
second = (second + first) % M;
else if (s[i - 1] == '2' && s[i] <= '6' )
second = (second + first) % M;
else if (s[i - 1] == '*' )
second = (second + (s[i] <= '6' ? 2 : 1) *
first) % M;
}
first = temp;
}
return ( int )second;
}
int main()
{
string s = "*" ;
cout << waysOfDecoding(s);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int M = 1000000007 ;
static int waysOfDecoding(String s)
{
long first = 1 , second
= s.charAt( 0 ) == '*'
? 9
: s.charAt( 0 ) == '0' ? 0 : 1 ;
for ( int i = 1 ; i < s.length(); i++) {
long temp = second;
if (s.charAt(i) == '*' ) {
second = 9 * second;
if (s.charAt(i - 1 ) == '1' )
second = (second + 9 * first) % M;
else if (s.charAt(i - 1 ) == '2' )
second = (second + 6 * first) % M;
else if (s.charAt(i - 1 ) == '*' )
second = (second + 15 * first) % M;
}
else {
second = s.charAt(i) != '0' ? second : 0 ;
if (s.charAt(i - 1 ) == '1' )
second = (second + first) % M;
else if (s.charAt(i - 1 ) == '2'
&& s.charAt(i) <= '6' )
second = (second + first) % M;
else if (s.charAt(i - 1 ) == '*' )
second = (second
+ (s.charAt(i) <= '6' ? 2 : 1 )
* first)
% M;
}
first = temp;
}
return ( int )second;
}
public static void main(String[] args)
{
String s = "*" ;
System.out.println(waysOfDecoding(s));
}
}
|
Python3
M = 1000000007
def waysOfDecoding(s):
first = 1
second = 9 if (s[ 0 ] = = '*' ) else ( 0 if (s[ 0 ] = = '0' ) else 1 )
for i in range ( 1 , len (s)):
temp = second
if (s[i] = = '*' ):
second = 9 * second
if (s[i - 1 ] = = '1' ):
second = (second + 9 * first) % M
elif (s[i - 1 ] = = '2' ):
second = (second + 6 * first) % M
elif (s[i - 1 ] = = '*' ):
second = (second + 15 * first) % M
else :
second = second if (s[i] ! = '0' ) else 0
if (s[i - 1 ] = = '1' ):
second = (second + first) % M
elif (s[i - 1 ] = = '2' and s[i] < = '6' ):
second = (second + first) % M
elif (s[i - 1 ] = = '*' ):
second = (second + ( 2 if (s[i] < = '6' ) else 1 ) * first) % M
first = temp
return second
s = "*"
print (waysOfDecoding(s))
|
C#
using System;
class GFG{
static int M = 1000000007;
static int waysOfDecoding( string s)
{
long first = 1,
second = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
for ( int i = 1; i < s.Length; i++)
{
long temp = second;
if (s[i] == '*' )
{
second = 9 * second;
if (s[i - 1] == '1' )
second = (second + 9 * first) % M;
else if (s[i - 1] == '2' )
second = (second + 6 * first) % M;
else if (s[i - 1] == '*' )
second = (second + 15 * first) % M;
}
else
{
second = s[i] != '0' ? second : 0;
if (s[i - 1] == '1' )
second = (second + first) % M;
else if (s[i - 1] == '2' && s[i] <= '6' )
second = (second + first) % M;
else if (s[i - 1] == '*' )
second = (second + (s[i] <= '6' ? 2 : 1) *
first) % M;
}
first = temp;
}
return ( int )second;
}
static public void Main()
{
string s = "*" ;
Console.WriteLine(waysOfDecoding(s));
}
}
|
Javascript
<script>
let M = 1000000007;
function waysOfDecoding(s)
{
let first = 1,
second = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
for (let i = 1; i < s.length; i++)
{
let temp = second;
if (s[i] == '*' )
{
second = 9 * second;
if (s[i - 1] == '1' )
second = (second + 9 * first) % M;
else if (s[i - 1] == '2' )
second = (second + 6 * first) % M;
else if (s[i - 1] == '*' )
second = (second + 15 * first) % M;
}
else
{
second = s[i] != '0' ? second : 0;
if (s[i - 1] == '1' )
second = (second + first) % M;
else if (s[i - 1] == '2' && s[i] <= '6' )
second = (second + first) % M;
else if (s[i - 1] == '*' )
second = (second + (s[i] <= '6' ? 2 : 1) *
first) % M;
}
first = temp;
}
return second;
}
let s = "*" ;
document.write(waysOfDecoding(s));
</script>
|
Time complexity: O(n)
Auxiliary Space: O(1)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...