Count subsequences in first string which are anagrams of the second string
Last Updated :
17 Apr, 2023
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.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
#define SIZE 26
int binomialCoeff( int n, int k)
{
int res = 1;
if (k > n - k)
k = n - k;
for ( int i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
int countSubsequences(string str1, string str2)
{
int freq1[SIZE], freq2[SIZE];
int n1 = str1.size();
int n2 = str2.size();
memset (freq1, 0, sizeof (freq1));
memset (freq2, 0, sizeof (freq2));
for ( int i = 0; i < n1; i++)
freq1[str1[i] - 'a' ]++;
for ( int i = 0; i < n2; i++)
freq2[str2[i] - 'a' ]++;
int count = 1;
for ( int i = 0; i < SIZE; i++)
if (freq2[i] != 0) {
if (freq2[i] <= freq1[i])
count = count * binomialCoeff(freq1[i], freq2[i]);
else
return 0;
}
return count;
}
int main()
{
string str1 = "abacd" ;
string str2 = "abc" ;
cout << "Count = "
<< countSubsequences(str1, str2);
return 0;
}
|
Java
import java.util.*;
import java.lang.*;
public class GfG{
public final static int SIZE = 26 ;
public static int binomialCoeff( int n,
int k)
{
int res = 1 ;
if (k > n - k)
k = n - k;
for ( int i = 0 ; i < k; ++i)
{
res *= (n - i);
res /= (i + 1 );
}
return res;
}
public static int countSubsequences(String str,
String str3)
{
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();
for ( int i = 0 ; i < n1; i++)
freq1[str1[i] - 'a' ]++;
for ( int i = 0 ; i < n2; i++)
freq2[str2[i] - 'a' ]++;
int count = 1 ;
for ( int i = 0 ; i < SIZE; i++)
if (freq2[i] != 0 ) {
if (freq2[i] <= freq1[i])
count = count * binomialCoeff(freq1[i], freq2[i]);
else
return 0 ;
}
return count;
}
public static void main(String argc[])
{
String str1 = "abacd" ;
String str2 = "abc" ;
System.out.println( "Count = " +
countSubsequences(str1, str2));
}
}
|
Python
import numpy as np
SIZE = 26
def binomialCoeff(n, k):
res = 1
if (k > n - k):
k = n - k
for i in range ( 0 , k):
res = res * (n - i)
res = int (res / (i + 1 ))
return res
def countSubsequences(str1, str2):
freq1 = np.zeros( 26 , dtype = np. int )
freq2 = np.zeros( 26 , dtype = np. int )
n1 = len (str1)
n2 = len (str2)
for i in range ( 0 , n1):
freq1[ ord (str1[i]) - ord ( 'a' ) ] + = 1
for i in range ( 0 , n2):
freq2[ ord (str2[i]) - ord ( 'a' )] + = 1
count = 1
for i in range ( 0 , SIZE):
if (freq2[i] ! = 0 ):
if (freq2[i] < = freq1[i]):
count = count * binomialCoeff(freq1[i], freq2[i])
else :
return 0
return count
str1 = "abacd"
str2 = "abc"
ans = countSubsequences(str1, str2)
print ( "Count = " , ans)
|
C#
using System;
class GfG {
public static int SIZE = 26;
public static int binomialCoeff( int n,
int k)
{
int res = 1;
if (k > n - k)
k = n - k;
for ( int i = 0; i < k; ++i)
{
res *= (n - i);
res /= (i + 1);
}
return res;
}
public static int countSubsequences(String str,
String str3)
{
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;
for ( int i = 0; i < n1; i++)
freq1[str1[i] - 'a' ]++;
for ( int i = 0; i < n2; i++)
freq2[str2[i] - 'a' ]++;
int count = 1;
for ( int i = 0; i < SIZE; i++)
if (freq2[i] != 0) {
if (freq2[i] <= freq1[i])
count = count * binomialCoeff(freq1[i],
freq2[i]);
else
return 0;
}
return count;
}
public static void Main(String[] argc)
{
String str1 = "abacd" ;
String str2 = "abc" ;
Console.Write( "Count = " +
countSubsequences(str1, str2));
}
}
|
PHP
<?php
$SIZE = 26;
function binomialCoeff( $n , $k )
{
$res = 1;
if ( $k > $n - $k )
$k = $n - $k ;
for ( $i = 0; $i < $k ; ++ $i )
{
$res *= ( $n - $i );
$res /= ( $i + 1);
}
return $res ;
}
function countSubsequences( $str1 ,
$str2 )
{
global $SIZE ;
$freq1 = array ();
$freq2 = array ();
for ( $i = 0;
$i < $SIZE ; $i ++)
{
$freq1 [ $i ] = 0;
$freq2 [ $i ] = 0;
}
$n1 = strlen ( $str1 );
$n2 = strlen ( $str2 );
for ( $i = 0; $i < $n1 ; $i ++)
$freq1 [ord( $str1 [ $i ]) -
ord( 'a' )]++;
for ( $i = 0; $i < $n2 ; $i ++)
$freq2 [ord( $str2 [ $i ]) -
ord( 'a' )]++;
$count = 1;
for ( $i = 0; $i < $SIZE ; $i ++)
if ( $freq2 [ $i ] != 0)
{
if ( $freq2 [ $i ] <= $freq1 [ $i ])
$count = $count *
binomialCoeff( $freq1 [ $i ],
$freq2 [ $i ]);
else
return 0;
}
return $count ;
}
$str1 = "abacd" ;
$str2 = "abc" ;
echo ( "Count = " .
countSubsequences( $str1 ,
$str2 ));
?>
|
Javascript
<script>
var SIZE = 26
function binomialCoeff(n, k)
{
var res = 1;
if (k > n - k)
k = n - k;
for ( var i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
function countSubsequences(str1, str2)
{
var freq1 = Array(SIZE).fill(0),
freq2 = Array(SIZE).fill(0);
var n1 = str1.length;
var n2 = str2.length;
for ( var i = 0; i < n1; i++)
freq1[str1[i].charCodeAt(0) -
'a' .charCodeAt(0)]++;
for ( var i = 0; i < n2; i++)
freq2[str2[i].charCodeAt(0) -
'a' .charCodeAt(0)]++;
var count = 1;
for ( var i = 0; i < SIZE; i++)
if (freq2[i] != 0) {
if (freq2[i] <= freq1[i])
count =
count * binomialCoeff(freq1[i], freq2[i]);
else
return 0;
}
return count;
}
var str1 = "abacd" ;
var str2 = "abc" ;
document.write( "Count = "
+ countSubsequences(str1, str2));
</script>
|
Time Complexity: O(n1 + n2) + O(max), where n1 and n2 are the lengths of the input strings and max is the maximum frequency.
Auxiliary space: O(26). The algorithm uses two integer arrays of size 26 to store the frequency of characters in both strings, which takes O(26) space. Also, it uses some constant extra space to store some variables. Therefore, the overall space complexity of the algorithm is O(1).
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...