Open In App

POTD Solutions | 15 Nov’ 23 | Better String

Last Updated : 22 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

View all POTD Solutions

Welcome to the daily solutions of our PROBLEM OF THE DAY (POTD). We will discuss the entire problem step-by-step and work towards developing an optimized solution. This will not only help you brush up on your concepts of Dynamic Programming but will also help you build up problem-solving skills.

15th-nov

POTD Solution 15 November 2023

We recommend you to try this problem on our GeeksforGeeks Practice portal first, and maintain your streak to earn Geeksbits and other exciting prizes, before moving towards the solution.
POTD 15th Nov

POTD 15 November: Better String:

Given a pair of strings of equal lengths, Geek wants to find the better string. The better string is the string having more number of distinct subsequences.
If both the strings have an equal count of distinct subsequences then return str1.

Examples:

Input:str1 = “gfg”, str2 = “ggg”
Output: “gfg”
Explanation: “gfg” has 6 distinct subsequences whereas “ggg” has 3 distinct subsequences.

Input: str1 = “a”, str2 = “b”
Output: “a”
Explanation: Both the strings has only 1 distinct subsequence.

Better String using Dynamic Programming:

The idea is to Dynamic Programming by maintaining an array dp, where dp[i] represents the count of distinct subsequences of the string up to length i. You can iteratively compute dp[i] based on the characters encountered in the string.

Step-by-step approach:

  • Initialize a vector last of size 26 to store the last occurrence index of each lowercase English alphabet and a dynamic programming array dp of size n+1, where n is the length of the input string str. dp[i] will represent the count of distinct subsequences of the string up to length i.
  • Iterate through the characters of the input string from left to right (index i from 1 to n)
    • Calculate dp[i] as twice the value of dp[i-1].
    • If the current character has occurred before (i.e., last[str[i-1] – ‘a’] is not -1), subtract dp[last[str[i-1] – ‘a’]] from dp[i] to remove the subsequences that end with the previous occurrence of the current character. Be sure to add mod and take the result modulo mod to ensure non-negative values.
    • Update last[str[i-1] – ‘a’] with the current index i-1 to mark the occurrence of the current character.
    • Return dp[n] as the answer
  • Call the countSub function and store the distinct subsequences for str1 in the integer a and store the distinct subsequences for str2 in the integer b.
  • If a is greater than or equal to b then return str1, else return str2.

Below is the implementation of the above approach:

C++




#include <string>
#include <vector>
using namespace std;
  
class Solution {
public:
    // Function to count the number of distinct subsequences
    int countSub(string s)
    {
        int n = s.size();
  
        // dp array to store counts
        vector<int> dp(n + 1, 0);
  
        // Empty string has one subsequence
        dp[0] = 1;
  
        // To store the last occurrence index of each
        // character
        vector<int> last(26, -1);
  
        for (int i = 1; i <= n; i++) {
  
            // Double the count from the previous position
            dp[i] = 2 * dp[i - 1];
  
            // If the current character has occurred before
            if (last[s[i - 1] - 97] != -1) {
  
                // Subtract the count of subsequences ending
                // at the last occurrence
                dp[i] = dp[i] - dp[last[s[i - 1] - 97]];
            }
            // Update the last occurrence index of the
            // current character
            last[s[i - 1] - 97] = i - 1;
        }
  
        // Return the total count of distinct subsequences
        return dp[n];
    }
  
    // Function to compare two strings based on the count of
    // distinct subsequences
    string betterString(string str1, string str2)
    {
        int a = countSub(str1);
        int b = countSub(str2);
  
        if (a >= b)
            return str1;
        else
            return str2;
    }
};


Java




public class Solution {
  
    // Function to count the number of distinct subsequences
    public int countSub(String s)
    {
        int n = s.length();
  
        // dp array to store counts
        int[] dp = new int[n + 1];
        Arrays.fill(dp, 0);
  
        // Empty string has one subsequence
        dp[0] = 1;
  
        // To store the last occurrence index of each
        // character
        int[] last = new int[26];
        Arrays.fill(last, -1);
  
        for (int i = 1; i <= n; i++) {
            // Double the count from the previous position
            dp[i] = 2 * dp[i - 1];
  
            // If the current character has occurred before
            if (last[s.charAt(i - 1) - 'a'] != -1) {
                // Subtract the count of subsequences ending
                // at the last occurrence
                dp[i] = dp[i]
                        - dp[last[s.charAt(i - 1) - 'a']];
            }
            // Update the last occurrence index of the
            // current character
            last[s.charAt(i - 1) - 'a'] = i - 1;
        }
  
        // Return the total count of distinct subsequences
        return dp[n];
    }
  
    // Function to compare two strings based on the count of
    // distinct subsequences
    public String betterString(String str1, String str2)
    {
        int a = countSub(str1);
        int b = countSub(str2);
  
        if (a >= b)
            return str1;
        else
            return str2;
    }
}


Python3




class Solution:
  
    # Function to count the number of distinct subsequences
    def count_sub(self, s):
        n = len(s)
  
        # dp list to store counts
        dp = [0] * (n + 1)
  
        # Empty string has one subsequence
        dp[0] = 1
  
        # To store the last occurrence index of each character
        last = [-1] * 26
  
        for i in range(1, n + 1):
           # Double the count from the previous position
            dp[i] = 2 * dp[i - 1]
  
            # If the current character has occurred before
            if last[ord(s[i - 1]) - 97] != -1:
               # Subtract the count of subsequences ending at the last occurrence
                dp[i] = dp[i] - dp[last[ord(s[i - 1]) - 97]]
  
             # Update the last occurrence index of the current character
            last[ord(s[i - 1]) - 97] = i - 1
  
        # Return the total count of distinct subsequences
        return dp[n]
  
    # Function to compare two strings based on the count of distinct subsequences
    def betterString(self, str1, str2):
        a = self.count_sub(str1)
        b = self.count_sub(str2)
  
        if a >= b:
            return str1
        else:
            return str2


Time Complexity: O(n),As we call countSub function two times and in this we iterate through the string once, processing each character in constant time, where n is the length of the input string.
Auxiliary Space: O(n), As we have used a dp array of size n+1 and last array of size 26. So total space complexity becomes O(n).



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads