Count subsequences in first string which are anagrams of the second string

Given two strings str1 and str2 of length n1 and n2 respectively. The problem is to count all the subsequences of str1 which are anagrams of str2.

Examples:

Input : str1 = "abacd", str2 = "abc"
Output : 2
Index of characters in the 2 subsequences are:
{0, 1, 3} = {a, b, c} = abc and
{1, 2, 3} = {b, a, c} = bac
The above two subsequences of str1 
are anagrams of str2.

Input : str1 = "geeksforgeeks", str2 = "geeks" 
Output : 48



Approach: Create two arrays freq1[] and freq2[] each of size ’26’ implemented as hash tables to store the frequencies of each character of str1 and str2 respectively. Let n1 and n2 be the lengths of str1 and str2 respectively. Now implement the following algorithm:

countSubsequences(str1, str2)
        for i = 0 to n1-1
        freq1[str1[i] - 'a']++
    for i = 0 n2-1    
        freq2[str2[i] - 'a']++

    Initialize count = 1    
    for i = 0 to 25
        if freq2[i] != 0 then
            if freq2[i] <= freq1[i] then
            count = count * binomialCoeff(freq1[i], freq2[i])
        else
            return 0    
        return count

Let freq1[i] is represented as n and freq2[i] as r. Now, binomialCoeff(n, r) mentioned in the algorithm above is nothing but binomial coefficient nCr .Refer this post for its implementation.

Explanation:
Let frequency of some character say ch in ‘str2’ is ‘x’ and in ‘str1’ is ‘y’. If y < x, then no subsequence of 'str1' exists which could be an anagram of 'str2'. Otherwise yCx gives the number of occurrences of ch selected which will contribute to the total count of required subsequences.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation to
// count subsequences in 
// first string which are  
// anagrams of the second
// string
#include <bits/stdc++.h>
using namespace std;
  
#define SIZE 26
  
// Returns value of Binomial
// Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
    int res = 1;
  
    // Since C(n, k) = C(n, n-k)
    if (k > n - k)
        k = n - k;
  
    // Calculate value of
    // [n * (n-1) *---* (n-k+1)] /
    // [k * (k-1) *----* 1]
    for (int i = 0; i < k; ++i) {
        res *= (n - i);
        res /= (i + 1);
    }
  
    return res;
}
  
// function to count subsequences 
// in first string which are 
// anagrams of the second string
int countSubsequences(string str1, string str2)
{
    // hash tables to store frequencies 
    // of each character
    int freq1[SIZE], freq2[SIZE];
  
    int n1 = str1.size();
    int n2 = str2.size();
  
    // Initialize
    memset(freq1, 0, sizeof(freq1));
    memset(freq2, 0, sizeof(freq2));
  
    // store frequency of each
    // character of 'str1'
    for (int i = 0; i < n1; i++)
        freq1[str1[i] - 'a']++;
  
    // store frequency of each 
    // character of 'str2'
    for (int i = 0; i < n2; i++)
        freq2[str2[i] - 'a']++;
  
    // to store the total count
    // of subsequences
    int count = 1;
  
    for (int i = 0; i < SIZE; i++)
  
        // if character (i + 'a') 
        // exists in 'str2'
        if (freq2[i] != 0) {
  
                // if this character's frequency 
                // in 'str2' in less than or
                // equal to its frequency in 
                // 'str1' then accumulate its 
                // contribution to the count
                // of subsequences. If its 
                // frequency in 'str1' is 'n' 
                // and in 'str2' is 'r', then 
                // its contribution wil be nCr,
                //  where C is the binomial 
                // coefficient.
            if (freq2[i] <= freq1[i])
                count = count * binomialCoeff(freq1[i], freq2[i]);
  
            // else return 0 as there could
            // be no subsequence which is an
            // anagram of 'str2'
            else
                return 0;
        }
  
    // required count of subsequences
    return count;
}
  
// Driver program to test above
int main()
{
    string str1 = "abacd";
    string str2 = "abc";
    cout << "Count = "
        << countSubsequences(str1, str2);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation to
// count subsequences in 
// first string which are 
// anagrams of the second
// string
import java.util.*;
import java.lang.*;
  
public class GfG{
      
    public final static int SIZE = 26;
      
    // Returns value of Binomial
    // Coefficient C(n, k)
    public static int binomialCoeff(int n, 
                                    int k)
    {
        int res = 1;
  
        // Since C(n, k) = C(n, n-k)
        if (k > n - k)
            k = n - k;
  
        // Calculate value of 
        // [n * (n-1) *---* (n-k+1)] /
        // [k * (k-1) *----* 1]
        for (int i = 0; i < k; ++i) 
        {
            res *= (n - i);
            res /= (i + 1);
        }
  
        return res;
    }
  
    // function to count subsequences 
    // in first string which are 
    // anagrams of the second string
    public static int countSubsequences(String str, 
                                        String str3)
    {
        // hash tables to store frequencies 
        // of each character
        int[] freq1 = new int [SIZE]; 
        int[] freq2 = new int [SIZE];
  
        char[] str1 = str.toCharArray();
        char[] str2 = str3.toCharArray();
          
        int n1 = str.length();
        int n2 = str3.length();
  
        // store frequency of each
        // character of 'str1'
        for (int i = 0; i < n1; i++)
            freq1[str1[i] - 'a']++;
  
        // store frequency of each 
        // character of 'str2'
        for (int i = 0; i < n2; i++)
            freq2[str2[i] - 'a']++;
  
        // to store the total count
        // of subsequences
        int count = 1;
  
        for (int i = 0; i < SIZE; i++)
  
            // if character (i + 'a')
            // exists in 'str2'
            if (freq2[i] != 0) {
  
                // if this character's frequency 
                // in 'str2' in less than or
                // equal to its frequency in 
                // 'str1' then accumulate its 
                // contribution to the count
                // of subsequences. If its 
                // frequency in 'str1' is 'n' 
                // and in 'str2' is 'r', then 
                // its contribution wil be nCr,
                // where C is the binomial 
                // coefficient.
                if (freq2[i] <= freq1[i])
                    count = count * binomialCoeff(freq1[i], freq2[i]);
  
                // else return 0 as there could
                // be no subsequence which is an
                // anagram of 'str2'
                else
                    return 0;
            }
  
        // required count of subsequences
        return count;
    }
      
    // Driver function
    public static void main(String argc[])
    {
        String str1 = "abacd";
        String str2 = "abc";
          
        System.out.println("Count = " +
        countSubsequences(str1, str2));
    }
}
  
/* This code is contributed by Sagar Shukla */

chevron_right


Python

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation to count
# subsequences in first which are 
# anagrams of the second
  
# import library
import numpy as np
  
SIZE = 26
  
# Returns value of Binomial
# Coefficient C(n, k)
def binomialCoeff(n, k):
      
    res = 1
  
    # Since C(n, k) = C(n, n-k)
    if (k > n - k):
        k = n - k
  
    # Calculate value of
    # [n * (n-1) *---* (n-k+1)] /
    # [k * (k-1) *----* 1]
    for i in range(0, k):
        res = res * (n - i)
        res = int(res / (i + 1))
      
    return res
  
  
# Function to count subsequences 
# in first which are anagrams
# of the second 
def countSubsequences(str1, str2):
      
    # Hash tables to store frequencies 
    # of each character
    freq1 = np.zeros(26, dtype = np.int
    freq2 = np.zeros(26, dtype = np.int
  
    n1 = len(str1)
    n2 = len(str2)
  
    # Store frequency of each
    # character of 'str1'
    for i in range(0, n1):
        freq1[ord(str1[i]) - ord('a') ] += 1
  
    # Store frequency of each 
    # character of 'str2'
    for i in range(0, n2):
          
        freq2[ord(str2[i]) - ord('a')] += 1
  
    # To store the total count
    # of subsequences
    count = 1
  
    for i in range(0, SIZE):
          
        # if character (i + 'a') 
        # exists in 'str2'
        if (freq2[i] != 0):
            # if this character's frequency 
            # in 'str2' in less than or
            # equal to its frequency in 
            # 'str1' then accumulate its 
            # contribution to the count
            # of subsequences. If its 
            # frequency in 'str1' is 'n' 
            # and in 'str2' is 'r', then 
            # its contribution wil be nCr,
            # where C is the binomial 
            # coefficient.
            if (freq2[i] <= freq1[i]):
                count = count * binomialCoeff(freq1[i], freq2[i])
  
            # else return 0 as there could
            # be no subsequence which is an
            # anagram of 'str2'
            else:
                return 0
          
    # required count of subsequences
    return count
  
# Driver code
str1 = "abacd"
str2 = "abc"
ans = countSubsequences(str1, str2)
print ("Count = ", ans)
  
  
# This code contributed by saloni1297

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation to
// count subsequences in 
// first string which are 
// anagrams of the second
// string
using System;
  
class GfG {
      
    public static int SIZE = 26;
      
    // Returns value of Binomial
    // Coefficient C(n, k)
    public static int binomialCoeff(int n, 
                                    int k)
    {
        int res = 1;
  
        // Since C(n, k) = C(n, n-k)
        if (k > n - k)
            k = n - k;
  
        // Calculate value of 
        // [n * (n-1) *---* (n-k+1)] /
        // [k * (k-1) *----* 1]
        for (int i = 0; i < k; ++i) 
        {
            res *= (n - i);
            res /= (i + 1);
        }
  
        return res;
    }
  
    // function to count subsequences 
    // in first string which are 
    // anagrams of the second string
    public static int countSubsequences(String str, 
                                        String str3)
    {
        // hash tables to store frequencies 
        // of each character
        int[] freq1 = new int [SIZE]; 
        int[] freq2 = new int [SIZE];
  
        char[] str1 = str.ToCharArray();
        char[] str2 = str3.ToCharArray();
          
        int n1 = str.Length;
        int n2 = str3.Length;
  
        // store frequency of each
        // character of 'str1'
        for (int i = 0; i < n1; i++)
            freq1[str1[i] - 'a']++;
  
        // store frequency of each 
        // character of 'str2'
        for (int i = 0; i < n2; i++)
            freq2[str2[i] - 'a']++;
  
        // to store the total count
        // of subsequences
        int count = 1;
  
        for (int i = 0; i < SIZE; i++)
  
            // if character (i + 'a')
            // exists in 'str2'
            if (freq2[i] != 0) {
  
                // if this character's frequency 
                // in 'str2' in less than or
                // equal to its frequency in 
                // 'str1' then accumulate its 
                // contribution to the count
                // of subsequences. If its 
                // frequency in 'str1' is 'n' 
                // and in 'str2' is 'r', then 
                // its contribution wil be nCr,
                // where C is the binomial 
                // coefficient.
                if (freq2[i] <= freq1[i])
                    count = count * binomialCoeff(freq1[i], 
                                                  freq2[i]);
  
                // else return 0 as there could
                // be no subsequence which is an
                // anagram of 'str2'
                else
                    return 0;
            }
  
        // required count of subsequences
        return count;
    }
      
    // Driver code
    public static void Main(String[] argc)
    {
        String str1 = "abacd";
        String str2 = "abc";
          
        Console.Write("Count = " +
        countSubsequences(str1, str2));
    }
}
  
// This code is contributed by parashar

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// PHP implementation to
// count subsequences in 
// first $which are 
// anagrams of the second
// string
$SIZE = 26;
  
// Returns value of Binomial
// Coefficient C(n, k)
function binomialCoeff($n, $k)
{
    $res = 1;
  
    // Since C(n, k) = C(n, n-k)
    if ($k > $n - $k)
        $k = $n - $k;
  
    // Calculate value of
    // [n * (n-1) *---* (n-k+1)] /
    // [k * (k-1) *----* 1]
    for ($i = 0; $i < $k; ++$i)
    {
        $res *= ($n - $i);
        $res /= ($i + 1);
    }
  
    return $res;
}
  
// function to count 
// subsequences in 
// first string which 
// are anagrams of the
// second string
function countSubsequences($str1,
                           $str2)
{
    global $SIZE;
      
    // hash tables to
    // store frequencies 
    // of each character
    $freq1 = array();
    $freq2 = array();
  
    // Initialize
    for ($i = 0; 
         $i < $SIZE; $i++)
    {
        $freq1[$i] = 0;
        $freq2[$i] = 0;
    
    $n1 = strlen($str1);
    $n2 = strlen($str2);
  
    // store frequency of each
    // character of 'str1'
    for ($i = 0; $i < $n1; $i++)
        $freq1[ord($str1[$i]) - 
               ord('a')]++;
  
    // store frequency of each 
    // character of 'str2'
    for ($i = 0; $i < $n2; $i++)
        $freq2[ord($str2[$i]) - 
               ord('a')]++;
  
    // to store the total count
    // of subsequences
    $count = 1;
  
    for ($i = 0; $i < $SIZE; $i++)
  
        // if character (i + 'a') 
        // exists in 'str2'
        if ($freq2[$i] != 0)
        {
  
            // if this character's frequency 
            // in 'str2' in less than or
            // equal to its frequency in 
            // 'str1' then accumulate its 
            // contribution to the count
            // of subsequences. If its 
            // frequency in 'str1' is 'n' 
            // and in 'str2' is 'r', then 
            // its contribution wil be nCr,
            // where C is the binomial 
            // coefficient.
            if ($freq2[$i] <= $freq1[$i])
                $count = $count
                         binomialCoeff($freq1[$i], 
                                       $freq2[$i]);
  
            // else return 0 as there 
            // could be no subsequence 
            // which is an anagram of
            // 'str2'
            else
                return 0;
        }
  
    // required count 
    // of subsequences
    return $count;
}
  
// Driver Code
$str1 = "abacd";
$str2 = "abc";
echo ("Count = ".
       countSubsequences($str1,
                         $str2));
  
// This code is contributed by 
// Manish Shaw(manishshaw1)
?>

chevron_right



Output :

Count = 2

Time Complexity: O(n1 + n2) + O(max), where max is the maximum frequency.



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.





Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.