CCCPaste Login

Count Encodings

#include 

using namespace std;

/*
QUESTION - https://www.youtube.com/watch?v=jFZmBQ569So&list=PL-Jc9J83PIiG8fE6rj9F5a6uyQ5WPdqKy&index=20 (Count the number of Encodings)
*/


void getEncodings(string digits, string path, vector < char > & encodings) {
    //base case
    //string is empty, which means we have processed all digits
    if (digits.empty()) {
        cout << path << '\n';
        return;
    }

    //invalid case
    //If the first char is '0', the prefixes formed by it will be invalid, i.e. '0' & "0i"
    //eg "04356" => prefixes formed => oneChar = '0' & twoChar = "04" which are both invalid, so we can directly return
    if (digits[0] == '0') {
        return;
    }

    // levels - digits (the whole string)
    // options - the starting 2 prefixes of digits

    // one digit at a time
    int oneChar = stoi(digits.substr(0, 1));
    getEncodings(digits.substr(1), path + encodings[oneChar], encodings);

    //two digits at a time
    //we can only get a substring of 2 length if the string is atleast of length = 2
    if (digits.size() >= 2) {
        int twoChar = stoi(digits.substr(0, 2));
        //We can only have this call if twoChar corresponds to a valid encoding
        // substring of length 2, which is: 10 <= twoChar <= 26
        if (twoChar >= 10 && twoChar <= 26) {
            getEncodings(digits.substr(2), path + encodings[twoChar], encodings);
        }
    }
}

int getEncodingsMemo(string digits, vector < char > & encodings, unordered_map < string, int > & memo) {
    /*
    The only thing changing here is digits
    So we should be able to memoise the code with a single key = digits.
    Definition = memo(digits) = Number of encodings possible when string = digits.
    */
    if (digits.empty()) {
        return 1;
    }

    if (digits[0] == '0') {
        return 0;
    }

    //memo Check
    if (memo.count(digits) > 0) {
        return memo[digits];
    }

    int totalEncodingsOneChar = 0, totalEncodingsTwoChar = 0;
    //one digit at a time
    int oneChar = stoi(digits.substr(0, 1));
    totalEncodingsOneChar = getEncodingsMemo(digits.substr(1), encodings, memo);

    //two digits at a time
    if (digits.size() >= 2) {
        int twoChar = stoi(digits.substr(0, 2));
        // substring of length 2, which is: 10 <= twoChar <= 26
        if (twoChar >= 10 && twoChar <= 26) {
            totalEncodingsTwoChar = getEncodingsMemo(digits.substr(2), encodings, memo);
        }
    }
    return memo[digits] = totalEncodingsOneChar + totalEncodingsTwoChar;
}

int getEncodingsDP(string & digits) {
  /*
  Storage & Meaning - dp[i] = Number of encodings possible for strings starting at index i (upto n - 1).
  */
  int n = digits.size();
  vector dp(n, 0);
   
  /*
  Direction - Smallest Problem at: dp[n - 1](string starting at index [n - 1] and ending at [n - 1])
              Largest Problem at: dp[0] (String starting at index 0, original string)
               
  */
  //edge case
  dp[n - 1] = digits[n - 1] == '0' ? 0 : 1;
   
   
  /*
  Travel & Solve - Travel from smallest to largest problem to get the answer to original problem
  */
  for(int i = n - 2; i >= 0; i--){
      if(digits[i] != '0'){
          dp[i] += dp[i + 1];
          if(i <= n - 2){
            int twoCharInt = stoi(digits.substr(i, 2));
            if(twoCharInt >= 10 && twoCharInt <= 26){
                dp[i] += i == n - 2 ? 1 : dp[i + 2];
            }
          }
      }
      
  }
  return dp[0];
}




int main() {
    // your code goes here
    string digits;
    cin >> digits;

    vector < char > encodings(27, -1);
    for (int i = 1; i <= 26; i++) {
        encodings[i] = (char)(i - 1 + 'a');
    }
    //Recursive Call with print
    //getEncodings(digits, "", encodings);

    //Memo Call
    // unordered_map < string, int > memo;
    // cout << getEncodingsMemo(digits, encodings, memo) << '\n';
    // cout << stoi("03") << '\n';
    //DP Call
    cout << getEncodingsDP(digits) << '\n';
}