Thursday, December 26, 2024
Google search engine
HomeLanguagesDynamic ProgrammingFind number of times a string occurs as a subsequence in given...

Find number of times a string occurs as a subsequence in given string

Given two strings, find the number of times the second string occurs in the first string, whether continuous or discontinuous.

Examples: 

Input:  
string a = "neveropen"
string b = "Gks"

Output: 4

Explanation:  
The four strings are - (Check characters marked in bold)
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks

If we carefully analyze the given problem, we can see that it can be easily divided into sub-problems. The idea is to process all characters of both strings one by one starting from either from left or right side. Let us traverse from right corner, there are two possibilities for every pair of character being traversed. 

m: Length of str1 (first string)
n: Length of str2 (second string)

If last characters of two strings are same, 
   1. We consider last characters and get count for remaining 
      strings. So we recur for lengths m-1 and n-1. 
   2. We can ignore last character of first string and 
      recurse for lengths m-1 and n.
else 
If last characters are not same, 
   We ignore last character of first string and 
   recurse for lengths m-1 and n.

Below is the implementation of above Naive recursive solution – 

C++




// A Naive recursive C++ program to find the number of
// times the second string occurs in the first string,
// whether continuous or discontinuous
#include <iostream>
using namespace std;
 
// Recursive function to find the number of times
// the second string occurs in the first string,
// whether continuous or discontinuous
int count(string a, string b, int m, int n)
{
    // If both first and second string is empty,
    // or if second string is empty, return 1
    if ((m == 0 && n == 0) || n == 0)
        return 1;
 
    // If only first string is empty and second
    // string is not empty, return 0
    if (m == 0)
        return 0;
 
    // If last characters are same
    // Recur for remaining strings by
    // 1. considering last characters of both strings
    // 2. ignoring last character of first string
    if (a[m - 1] == b[n - 1])
        return count(a, b, m - 1, n - 1) +
               count(a, b, m - 1, n);
    else
        // If last characters are different, ignore
        // last char of first string and recur for
        // remaining string
        return count(a, b, m - 1, n);
}
 
// Driver code
int main()
{
    string a = "neveropen";
    string b = "Gks";
 
    cout << count(a, b, a.size(), b.size()) << endl;
 
    return 0;
}


Java




// A Naive recursive java program to find the number of
// times the second string occurs in the first string,
// whether continuous or discontinuous
import java.io.*;
 
class GFG
{
     
    // Recursive function to find the number of times
    // the second string occurs in the first string,
    // whether continuous or discontinuous
    static int count(String a, String b, int m, int n)
    {
        // If both first and second string is empty,
        // or if second string is empty, return 1
        if ((m == 0 && n == 0) || n == 0)
            return 1;
     
        // If only first string is empty and
        // second string is not empty, return 0
        if (m == 0)
            return 0;
     
        // If last characters are same
        // Recur for remaining strings by
        // 1. considering last characters of
        // both strings
        // 2. ignoring last character of
        // first string
        if (a.charAt(m - 1) == b.charAt(n - 1))
            return count(a, b, m - 1, n - 1) +
                   count(a, b, m - 1, n);
        else
            // If last characters are different, 
            // ignore last char of first string
            // and recur for  remaining string
            return count(a, b, m - 1, n);
    }
     
    // Driver code
    public static void main (String[] args)
    {
        String a = "neveropen";
        String b = "Gks";
        System.out.println( count(a, b, a.length(), b.length())) ;
     
    }
}
 
// This code is contributed by vt_m


Python 3




# A Naive recursive Python program
# to find the number of times the
# second string occurs in the first
# string, whether continuous or
# discontinuous
 
# Recursive function to find the
# number of times the second string
# occurs in the first string,
# whether continuous or discontinuous
def count(a, b, m, n):
 
    # If both first and second string
    # is empty, or if second string
    # is empty, return 1
    if ((m == 0 and n == 0) or n == 0):
        return 1
 
    # If only first string is empty
    # and second string is not empty,
    # return 0
    if (m == 0):
        return 0
 
    # If last characters are same
    # Recur for remaining strings by
    # 1. considering last characters
    #    of both strings
    # 2. ignoring last character
    #    of first string
    if (a[m - 1] == b[n - 1]):
        return (count(a, b, m - 1, n - 1) +
                count(a, b, m - 1, n))
    else:
         
        # If last characters are different,
        # ignore last char of first string
        # and recur for remaining string
        return count(a, b, m - 1, n)
 
# Driver code
a = "neveropen"
b = "Gks"
 
print(count(a, b, len(a),len(b)))
 
# This code is contributed by ash264


C#




// A Naive recursive C# program to find the number of
// times the second string occurs in the first string,
// whether continuous or discontinuous
using System;
  
class GFG
{
      
    // Recursive function to find the number of times
    // the second string occurs in the first string,
    // whether continuous or discontinuous
    static int count(string a, string b, int m, int n)
    {
        // If both first and second string is empty,
        // or if second string is empty, return 1
        if ((m == 0 && n == 0) || n == 0)
            return 1;
      
        // If only first string is empty and
        // second string is not empty, return 0
        if (m == 0)
            return 0;
      
        // If last characters are same
        // Recur for remaining strings by
        // 1. considering last characters of
        // both strings
        // 2. ignoring last character of
        // first string
        if (a[m - 1] == b[n - 1])
            return count(a, b, m - 1, n - 1) +
                   count(a, b, m - 1, n);
        else
            // If last characters are different, 
            // ignore last char of first string
            // and recur for  remaining string
            return count(a, b, m - 1, n);
    }
      
    // Driver code
    public static void Main ()
    {
        string a = "neveropen";
        string b = "Gks";
        Console.Write( count(a, b, a.Length, b.Length) );
      
    }
}
  
// This code is contributed by nitin mittal


PHP




<?php
// A Naive recursive PHP program to find the number of
// times the second string occurs in the first string,
// whether continuous or discontinuous
  
// Recursive function to find the number of times
// the second string occurs in the first string,
// whether continuous or discontinuous
function count_1($a, $b, $m, $n)
{
    // If both first and second string is empty,
    // or if second string is empty, return 1
    if (($m == 0 && $n == 0) || $n == 0)
        return 1;
  
    // If only first string is empty and second
    // string is not empty, return 0
    if ($m == 0)
        return 0;
  
    // If last characters are same
    // Recur for remaining strings by
    // 1. considering last characters of both strings
    // 2. ignoring last character of first string
    if ($a[$m - 1] == $b[$n - 1])
        return count_1($a, $b, $m - 1, $n - 1) +
               count_1($a, $b, $m - 1, $n);
    else
        // If last characters are different, ignore
        // last char of first string and recur for
        // remaining string
        return count_1($a, $b, $m - 1, $n);
}
  
// Driver code
 
$a = "neveropen";
$b = "Gks";
echo count_1($a, $b, strlen($a), strlen($b)) ."\n";
return 0;
?>


Javascript




<script>
// A Naive recursive javascript program to find the number of
// times the second string occurs in the first string,
// whether continuous or discontinuous
 
    // Recursive function to find the number of times
    // the second string occurs in the first string,
    // whether continuous or discontinuous
    function count( a,  b , m , n)
    {
     
        // If both first and second string is empty,
        // or if second string is empty, return 1
        if ((m == 0 && n == 0) || n == 0)
            return 1;
 
        // If only first string is empty and
        // second string is not empty, return 0
        if (m == 0)
            return 0;
 
        // If last characters are same
        // Recur for remaining strings by
        // 1. considering last characters of
        // both strings
        // 2. ignoring last character of
        // first string
        if (a[m - 1] == b[n - 1])
            return count(a, b, m - 1, n - 1) + count(a, b, m - 1, n);
        else
         
            // If last characters are different,
            // ignore last char of first string
            // and recur for remaining string
            return count(a, b, m - 1, n);
    }
 
    // Driver code
    var a = "neveropen";
    var b = "Gks";
    document.write(count(a, b, a.length, b.length));
 
// This code is contributed by Amit Katiyar
</script>


Output

4

The time complexity of above solution is exponential. If we carefully analyze, we can see that many sub-problems are solved again and again. Since same sub-problems are called again, this problem has Overlapping sub-problems property. So the problem has both properties (see this and this) of a dynamic programming problem. Like other typical Dynamic Programming problems, re-computations of same sub-problems can be avoided by constructing a temporary array that stores results of sub-problems.

Space Complexity: O(n)

We can solve it in 2 ways

1) Top-down DP

We can extend the recursion solution and stores the states of dp in 2d vector so that we don’t recompute the sub problems again.

C++




// A Memoization DP C++ program to find the number of
// times the second string occurs in the first string,
// whether continuous or discontinuous
#include <bits/stdc++.h>
using namespace std;
 
// Memoization DP function to find the number of times
// the second string occurs in the first string,
// whether continuous or discontinuous
int count(string a, string b, int m, int n,
          vector<vector<int> >& dp)
{
    // If both first and second string is empty,
    // or if second string is empty, return 1
    if ((m == 0 && n == 0) || n == 0)
        return 1;
 
    // If only first string is empty and second
    // string is not empty, return 0
    if (m == 0)
        return 0;
 
    if (dp[m][n] != -1) {
        return dp[m][n];
    }
    // If last characters are same
    // Recur for remaining strings by
    // 1. considering last characters of both strings
    // 2. ignoring last character of first string
    if (a[m - 1] == b[n - 1])
        return dp[m][n] = count(a, b, m - 1, n - 1, dp)
                          + count(a, b, m - 1, n, dp);
    else
        // If last characters are different, ignore
        // last char of first string and recur for
        // remaining string
        return dp[m][n] = count(a, b, m - 1, n, dp);
}
 
// Driver code
int main()
{
    string a = "neveropen";
    string b = "Gks";
    vector<vector<int> > dp(a.size() + 1,
                            vector<int>(b.size() + 1, -1));
    cout << count(a, b, a.size(), b.size(), dp) << endl;
 
    return 0;
}


Java




import java.util.Arrays;
 
public class Main
{
   
  // Memoization DP function to find the number of times
  // the second string occurs in the first string,
  // whether continuous or discontinuous
  public static int count(String a, String b, int m, int n,
                          int[][] dp)
  {
     
    // If both first and second string is empty,
    // or if second string is empty, return 1
    if ((m == 0 && n == 0) || n == 0)
      return 1;
 
    // If only first string is empty and second
    // string is not empty, return 0
    if (m == 0)
      return 0;
 
    if (dp[m][n] != -1) {
      return dp[m][n];
    }
     
    // If last characters are same
    // Recur for remaining strings by
    // 1. considering last characters of both strings
    // 2. ignoring last character of first string
    if (a.charAt(m - 1) == b.charAt(n - 1))
      return dp[m][n] = count(a, b, m - 1, n - 1, dp)
      + count(a, b, m - 1, n, dp);
    else
       
      // If last characters are different, ignore
      // last char of first string and recur for
      // remaining string
      return dp[m][n] = count(a, b, m - 1, n, dp);
  }
 
  // Driver code
  public static void main(String[] args) {
    String a = "neveropen";
    String b = "Gks";
    int[][] dp = new int[a.length() + 1][b.length() + 1];
    for (int[] row : dp)
      Arrays.fill(row, -1);
    System.out.println(count(a, b, a.length(), b.length(), dp));
  }
}
 
// This code is contributed by unstoppablepandu.


Python3




# A Memoization DP Python program to find the number of
# times the second string occurs in the first string,
# whether continuous or discontinuous
 
def count(a: str, b: str, m: int, n: int, dp: list) -> int:
    # If both first and second string is empty,
    # or if second string is empty, return 1
    if (m == 0 and n == 0) or n == 0:
        return 1
 
    # If only first string is empty and second
    # string is not empty, return 0
    if m == 0:
        return 0
 
    if dp[m][n] != -1:
        return dp[m][n]
 
    # If last characters are same
    # Recur for remaining strings by
    # 1. considering last characters of both strings
    # 2. ignoring last character of first string
    if a[m - 1] == b[n - 1]:
        dp[m][n] = count(a, b, m - 1, n - 1, dp) + count(a, b, m - 1, n, dp)
    else:
        # If last characters are different, ignore
        # last char of first string and recur for
        # remaining string
        dp[m][n] = count(a, b, m - 1, n, dp)
 
    return dp[m][n]
 
# Driver code
a = "neveropen"
b = "Gks"
dp = [[-1] * (len(b) + 1) for _ in range(len(a) + 1)]
print(count(a, b, len(a), len(b), dp))
 
# This code is contributed by phasing17.


C#




using System;
 
public class GFG
{
// Memoization DP function to find the number of times
// the second string occurs in the first string,
// whether continuous or discontinuous
public static int Count(string a, string b, int m, int n, int[,] dp)
{
// If both first and second string is empty,
// or if second string is empty, return 1
if ((m == 0 && n == 0) || n == 0)
return 1;
 
    // If only first string is empty and second
    // string is not empty, return 0
    if (m == 0)
        return 0;
 
    if (dp[m, n] != -1)
    {
        return dp[m, n];
    }
 
    // If last characters are same
    // Recur for remaining strings by
    // 1. considering last characters of both strings
    // 2. ignoring last character of first string
    if (a[m - 1] == b[n - 1])
        return dp[m, n] = Count(a, b, m - 1, n - 1, dp) + Count(a, b, m - 1, n, dp);
    else
        // If last characters are different, ignore
        // last char of first string and recur for
        // remaining string
        return dp[m, n] = Count(a, b, m - 1, n, dp);
}
 
// Driver code
public static void Main()
{
    string a = "neveropen";
    string b = "Gks";
    int[,] dp = new int[a.Length + 1, b.Length + 1];
    for (int i = 0; i <= a.Length; i++)
    {
        for (int j = 0; j <= b.Length; j++)
        {
            dp[i, j] = -1;
        }
    }
    Console.WriteLine(Count(a, b, a.Length, b.Length, dp));
}
}


Javascript




// A Memoization DP JavaScript program to find the number of
// times the second string occurs in the first string,
// whether continuous or discontinuous
function count(a, b, m, n, dp) {
 
    // If both first and second string is empty,
    // or if second string is empty, return 1
    if ((m == 0 && n == 0) || n == 0) {
        return 1;
    }
 
    // If only first string is empty and second
    // string is not empty, return 0
    if (m == 0) {
        return 0;
    }
 
    if (dp[m][n] != -1) {
        return dp[m][n];
    }
 
    // If last characters are same
    // Recur for remaining strings by
    // 1. considering last characters of both strings
    // 2. ignoring last character of first string
    if (a[m - 1] === b[n - 1]) {
        return (dp[m][n] =
            count(a, b, m - 1, n - 1, dp) +
            count(a, b, m - 1, n, dp)
        );
    } else {
     
        // If last characters are different, ignore
        // last char of first string and recur for
        // remaining string
        return (dp[m][n] = count(a, b, m - 1, n, dp));
    }
}
 
// Driver code
const a = "neveropen";
const b = "Gks";
const dp = Array.from({
        length: a.length + 1
    }, () =>
    Array(b.length + 1).fill(-1)
);
console.log(count(a, b, a.length, b.length, dp));


Output

4

Time complexity of above solutions is O(MN) excluding recursion stack space.

 Auxiliary space used by the program is O(MN).

2) Bottom-Up DP

Below is its implementation using Dynamic Programming – 

C++




// A Dynamic Programming based C++ program to find the
// number of times the second string occurs in the first
// string, whether continuous or discontinuous
#include <iostream>
using namespace std;
 
// Iterative DP function to find the number of times
// the second string occurs in the first string,
// whether continuous or discontinuous
int count(string a, string b)
{
    int m = a.length();
    int n = b.length();
 
    // Create a table to store results of sub-problems
    int lookup[m + 1][n + 1] = { { 0 } };
 
    // If first string is empty
    for (int i = 0; i <= n; ++i)
        lookup[0][i] = 0;
 
    // If second string is empty
    for (int i = 0; i <= m; ++i)
        lookup[i][0] = 1;
 
    // Fill lookup[][] in bottom up manner
    for (int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            // If last characters are same, we have two
            // options -
            // 1. consider last characters of both strings
            //    in solution
            // 2. ignore last character of first string
            if (a[i - 1] == b[j - 1])
                lookup[i][j] = lookup[i - 1][j - 1] +
                               lookup[i - 1][j];
                 
            else
                // If last character are different, ignore
                // last character of first string
                lookup[i][j] = lookup[i - 1][j];
        }
    }
 
    return lookup[m][n];
}
 
// Driver code
int main()
{
    string a = "neveropen";
    string b = "Gks";
 
    cout << count(a, b);
 
    return 0;
}


Java




// A Dynamic Programming based
// Java program to find the
// number of times the second
// string occurs in the first
// string, whether continuous
// or discontinuous
import java.io.*;
 
class GFG
{
     
// Iterative DP function to
// find the number of times
// the second string occurs
// in the first string, whether
// continuous or discontinuous
static int count(String a, String b)
{
    int m = a.length();
    int n = b.length();
 
    // Create a table to store
    // results of sub-problems
    int lookup[][] = new int[m + 1][n + 1];
 
    // If first string is empty
    for (int i = 0; i <= n; ++i)
        lookup[0][i] = 0;
 
    // If second string is empty
    for (int i = 0; i <= m; ++i)
        lookup[i][0] = 1;
 
    // Fill lookup[][] in
    // bottom up manner
    for (int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            // If last characters are
            // same, we have two options -
            // 1. consider last characters
            //    of both strings in solution
            // 2. ignore last character
            //    of first string
            if (a.charAt(i - 1) == b.charAt(j - 1))
                lookup[i][j] = lookup[i - 1][j - 1] +
                               lookup[i - 1][j];
                 
            else
                // If last character are
                // different, ignore last
                // character of first string
                lookup[i][j] = lookup[i - 1][j];
        }
    }
 
    return lookup[m][n];
}
 
// Driver Code
public static void main (String[] args)
{
    String a = "neveropen";
    String b = "Gks";
     
    System.out.println(count(a, b));
}
}
 
// This code is contributed by anuj_67.


Python3




# A Dynamic Programming based Python
# program to find the number of times
# the second string occurs in the first
# string, whether continuous or discontinuous
 
# Iterative DP function to find the 
# number of times the second string
# occurs in the first string,
# whether continuous or discontinuous
def count(a, b):
    m = len(a)
    n = len(b)
 
    # Create a table to store results of sub-problems
    lookup = [[0] * (n + 1) for i in range(m + 1)]
 
    # If first string is empty
    for i in range(n+1):
        lookup[0][i] = 0
 
    # If second string is empty
    for i in range(m + 1):
        lookup[i][0] = 1
 
    # Fill lookup[][] in bottom up manner
    for i in range(1, m + 1):
        for j in range(1, n + 1):
             
            # If last characters are same, 
            # we have two options -
            # 1. consider last characters of 
            # both strings in solution
            # 2. ignore last character of first string
            if a[i - 1] == b[j - 1]:
                lookup[i][j] = lookup[i - 1][j - 1] + lookup[i - 1][j]
                 
            else:
                # If last character are different, ignore
                # last character of first string
                lookup[i][j] = lookup[i - 1][j]
 
    return lookup[m][n]
 
# Driver code
if __name__ == '__main__':
    a = "neveropen"
    b = "Gks"
 
    print(count(a, b))
     
# this code is contributed by PranchalK


C#




// A Dynamic Programming based
// C# program to find the
// number of times the second
// string occurs in the first
// string, whether continuous
// or discontinuous
using System;
 
class GFG
{
     
// Iterative DP function to
// find the number of times
// the second string occurs
// in the first string, whether
// continuous or discontinuous
static int count(String a, String b)
{
    int m = a.Length;
    int n = b.Length;
 
    // Create a table to store
    // results of sub-problems
    int[,] lookup = new int[m + 1, n + 1];
 
    // If first string is empty
    for (int i = 0; i <= n; ++i)
        lookup[0, i] = 0;
 
    // If second string is empty
    for (int i = 0; i <= m; ++i)
        lookup[i, 0] = 1;
 
    // Fill lookup[][] in
    // bottom up manner
    for (int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            // If last characters are
            // same, we have two options -
            // 1. consider last characters
            // of both strings in solution
            // 2. ignore last character
            // of first string
            if (a[i - 1] == b[j - 1])
                lookup[i, j] = lookup[i - 1, j - 1] +
                            lookup[i - 1, j];
                 
            else
                // If last character are
                // different, ignore last
                // character of first string
                lookup[i, j] = lookup[i - 1, j];
        }
    }
 
    return lookup[m, n];
}
 
// Driver Code
public static void Main()
{
    String a = "neveropen";
    String b = "Gks";
     
    Console.WriteLine(count(a, b));
}
}
 
// This code is contributed
// by Akanksha Rai(Abby_akku)


PHP




<?php
// A Dynamic Programming based PHP program to find the
// number of times the second string occurs in the first
// string, whether continuous or discontinuous
 
// Iterative DP function to find the number of times
// the second string occurs in the first string,
// whether continuous or discontinuous
function count1($a, $b)
{
    $m = strlen($a);
    $n = strlen($b);
 
    // Create a table to store results of sub-problems
    $lookup = array_fill(0, $m + 1, array_fill(0, $n + 1, 0));
 
    // If second string is empty
    for ($i = 0; $i <= $m; ++$i)
        $lookup[$i][0] = 1;
 
    // Fill lookup[][] in bottom up manner
    for ($i = 1; $i <= $m; $i++)
    {
        for ($j = 1; $j <= $n; $j++)
        {
            // If last characters are same, we have two
            // options -
            // 1. consider last characters of both strings
            // in solution
            // 2. ignore last character of first string
            if ($a[$i - 1] == $b[$j - 1])
                $lookup[$i][$j] = $lookup[$i - 1][$j - 1] +
                            $lookup[$i - 1][$j];
                 
            else
                // If last character are different, ignore
                // last character of first string
                $lookup[$i][$j] = $lookup[$i - 1][$j];
        }
    }
 
    return $lookup[$m][$n];
}
 
// Driver code
 
    $a = "neveropen";
    $b = "Gks";
 
    echo count1($a, $b);
 
// This code is contributed by chandan_jnu
?>


Javascript




<script>
 
// A Dynamic Programming based
// Javascript program to find the
// number of times the second
// string occurs in the first
// string, whether continuous
// or discontinuous
 
// Iterative DP function to
// find the number of times
// the second string occurs
// in the first string, whether
// continuous or discontinuous
function count(a, b)
{
    var m = a.length;
    var n = b.length;
 
    // Create a table to store
    // results of sub-problems
    var lookup = Array(m + 1);
    for(var i = 0; i < m + 1; i++)
        lookup[i] = Array(n + 1).fill(0);
 
    // If first string is empty
    for(i = 0; i <= n; ++i)
        lookup[0][i] = 0;
 
    // If second string is empty
    for(i = 0; i <= m; ++i)
        lookup[i][0] = 1;
 
    // Fill lookup in
    // bottom up manner
    for(i = 1; i <= m; i++)
    {
        for(j = 1; j <= n; j++)
        {
             
            // If last characters are
            // same, we have two options -
            // 1. consider last characters
            // of both strings in solution
            // 2. ignore last character
            // of first string
            if (a.charAt(i - 1) == b.charAt(j - 1))
                lookup[i][j] = lookup[i - 1][j - 1] +
                               lookup[i - 1][j];
            else
             
                // If last character are
                // different, ignore last
                // character of first string
                lookup[i][j] = lookup[i - 1][j];
        }
    }
    return lookup[m][n];
}
 
// Driver Code
var a = "neveropen";
var b = "Gks";
 
document.write(count(a, b));
 
// This code is contributed by gauravrajput1
 
</script>


Output

4

Time complexity of above solutions is O(MN). 
Auxiliary space used by the program is O(MN).

Another Method : 

This method was contributed by Kunal Hotwani

We can solve this problem by considering the fact that, in the final subsequences that will be chosen in the count, the character at b[i] will always follow the character at b[i – 1] (by the definition of a subsequence). 

Using this fact, we count the total number of occurrences of string b, using an array of size equal to the length of string b.

We can create an array of size equal to n (b.size()),  the jth element in this array stores the number of subsequences in the string a which are equal to b[0]b[1]…b[j]. We will traverse the string a, each time updating all the values in this array. Let’s call this array count.

While traversing the string a, we will traverse the string b in reverse for each character of a, let’s say we are at the  ith character of a (a[i]) and we start the reverse traversal of the b, if the jth character of b (b[j]) is equal to a[i], a[i] can be appended to all the subsequences of a (traversed until now) which are equal to b[0]b[1]…b[j – 1] (number of these type of subsequences is stored in count[j -1]), making subsequences equal to b[0]b[1]…b[j] (number of these type of subsequences is stored in count[j]), thus count[j] can be increased by count[j – 1], when we encounter a character in string b which is equal to a[i].

NOTE : When j is equal to 0, the character a[i] cannot be appended to any subsequences, instead it can start a new subsequence equal to b[0], thus when a[i] is equal to b[0], we increase count[0] by 1 (As it stores the count all the subsequences of type b[0]).

Thus, in this method we are counting all the subsequences of a type b[0]b[1]…b[j] that can created using a particular character of a, a[i].

Finally, after traversing the complete string a, the final answer will be stored in count[n – 1], as we require the number of subsequences of type b[0]b[1]…b[n – 1]

The reason for traversal of b in reverse

Let us consider b = neveropen,  we will create the count array of size 5 and start the traversal of b string from front for each a[i].

When a[i] = ‘e’, we will first increase count[1](representing the first e in string b) by count[0], and then increase count[2](representing the second e in string b) by count[1], this not ideal because we always the need the value of count[j – 1] to represent the number of subsequences of type b[0]b[1]…b[j – 1] in the string a[0]a[1]…a[i – 1] as we cannot use the same ‘e’ twice in one subsequence (In this case count[1] will represent a[i] appended to all the subsequences of type b[0] and using this count[1] to update count[2] which will mean we use the same ‘e’ twice). 

Below is the code for this approach

C++




#include <bits/stdc++.h>
using namespace std;
 
int countWays(string S1, string S2)
{
    int m = S1.size(), n = S2.size();
    vector<int> count(n, 0);
      // Initialization to 0 is done because if a is not traversed yet,
      // no subsequence of any type b[0]b[1]...b[i] can exist, i.e. the
      // number is zero.
 
    for (int i = 0; i < m; i++)  // Traversing the string a
    {
        for (int j = n - 1; j >= 0; j--)  // Reverse traversal of b
        {
            if (S1[i] == S2[j])
            {
                  // This ternary expression checks weather j == 0,
                  // gives 1 if j == 0.
                count[j] += (j == 0 ? 1 : count[j - 1]);
            }
        }
    }
 
    return count[n - 1];
}
 
int main()
{
    string S1 = "neveropen", S2 = "neveropen";
    cout << countWays(S1, S2) << "\n";
    return 0;
}


Java




import java.util.*;
 
class GFG {
    public static int countWays(String s1, String s2)
    {
        int m = s1.length(), n = s2.length();
        int[] count = new int[n];
 
          // Initialization to 0 is done because if a is not traversed yet,
          // no subsequence of any type b[0]b[1]...b[i] can exist, i.e. the
          // number is zero.
        for (int i = 0; i < m; i++) { // Traversing the string a
            for (int j = n - 1; j >= 0; j--) { // Reverse traversal of b
                if (s1.charAt(i) == s2.charAt(j)) {
                   
                      // This ternary expression checks weather j == 0,
                      // gives 1 if j == 0.
                    count[j] += (j == 0 ? 1 : count[j - 1]);
                }
            }
        }
 
        return count[n - 1];
    }
 
    public static void main(String[] args)
    {
        String s1 = "neveropen", s2 = "neveropen";
        System.out.println(countWays(s1, s2));
    }
}
 
// This Code is Contributed by Prasad Kandekar(prasad264)


Python3




def countWays(S1, S2):
    m = len(S1)
    n = len(S2)
    count = [0] * n
     
    # Initialization to 0 is done because if a is not traversed yet,
    # no subsequence of any type b[0]b[1]...b[i] can exist, i.e. the
    # number is zero.
     
    for i in range(m): # Traversing the string a
        for j in range(n-1, -1, -1): # Reverse traversal of b
            if S1[i] == S2[j]:
               
                  # This ternary expression checks weather j == 0,
                # gives 1 if j == 0.
                count[j] += count[j-1] if j != 0 else 1
    return count[n-1]
 
S1 = "neveropen"
S2 = "neveropen"
print(countWays(S1, S2))
 
# This Code is Contributed by Prasad Kandekar(prasad264)


C#




using System;
 
public class GFG {
 
    static int countWays(string S1, string S2)
    {
        int m = S1.Length, n = S2.Length;
        int[] count = new int[n];
        // Initialization to 0 is done because if a is not traversed yet,
          // no subsequence of any type b[0]b[1]...b[i] can exist, i.e. the
          // number is zero.
 
        for (int i = 0; i < m; i++) // Traversing the string a
        {
            for (int j = n - 1; j >= 0; j--) // Reverse traversal of b
            {
                if (S1[i] == S2[j]) {
                     
                      // This ternary expression checks weather j == 0,
                      // gives 1 if j == 0.
                    count[j] += (j == 0 ? 1 : count[j - 1]);
                }
            }
        }
 
        return count[n - 1];
    }
 
    static void Main(string[] args)
    {
        string S1 = "neveropen", S2 = "neveropen";
        Console.WriteLine(countWays(S1, S2));
    }
}
 
// This Code is Contributed by Prasad Kandekar(prasad264)


Javascript




function countWays(s1, s2) {
    const m = s1.length,
        n = s2.length;
    const count = new Array(n).fill(0);
 
    // Initialization to 0 is done because if a is not traversed yet,
    // no subsequence of any type b[0]b[1]...b[i] can exist, i.e. the
    // number is zero.
    for (let i = 0; i < m; i++) { // Traversing the string a
        for (let j = n - 1; j >= 0; j--) { // Reverse traversal of b
            if (s1.charAt(i) == s2.charAt(j)) { // This ternary expression checks weather j == 0,
                // gives 1 if j == 0.
                count[j] += (j == 0 ? 1 : count[j - 1]);
            }
        }
    }
 
    return count[n - 1];
}
 
const s1 = "neveropen",
    s2 = "neveropen";
console.log(countWays(s1, s2));


Output

9

Time complexity of above solutions is O(MN). 
Auxiliary space used by the program is O(N).

This article is contributed by Aditya Goel. If you like neveropen and would like to contribute, you can also write an article using contribute.neveropen.org or mail your article to contribute@neveropen.org. See your article appearing on the neveropen main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
 

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments