Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Count anagrams having first character as a consonant and no pair of consonants or vowels placed adjacently

  • Last Updated : 24 Feb, 2021

Given a string S of length N, the task is to count the number of anagrams of S whose first character is a consonant and no pair of consonants or vowels are adjacent to each other.

Examples:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: S = “GADO”
Output: 4
Explanation:
The anagrams of string S satisfying the given conditions are GADO, GODA, DOGA, DAGO.
Therefore, the total number of such anagrams is 4.



Input: S = “AABCY”
Output: 6
Explanation:
The anagrams of the string S satisfying the given conditions are BACAY, BAYAC, CABAY, CAYAB, YABAC, YACAB.
Therefore, the total number of such anagrams is 6.

Naive Approach: The simplest approach is to generate all possible anagrams of the given string and count those anagrams that satisfy the given condition. Finally, print the count obtained.
Time Complexity: O(N!*N)
Auxiliary Space: O(1)

Efficient Approach: The above approach can also be optimized based on the following observations:

  • Strings that have an equal number of consonants and vowels satisfy the given condition.
  • Strings having one more consonant than vowel also satisfy the given condition.
  • Apart from these two conditions, the count of possible anagrams will always be 0.
  • Now, the problem can be solved by using a combinatorial formula. Consider there are C1, C2…, CN consonants and V1, V2, …, VN vowels in the string S and \sum C    and \sum C\sum V    denote the total number of consonants and vowels respectively, then the answer would be:

\frac{\sum C! * \sum V!}{(\sum C_1! *\sum C_2! * ... *C_N!)*(\sum V_1! *\sum V_2! * ... *V_N!)}

where, 
Ci is the count of ith consonant.
Vi is the count of ith vowel.

Follow the steps below to solve the problem:

  • Initialize a variable, say answer, to store the total count of anagrams.
  • Store the frequency of each character of the string S in a HashMap count.
  • Store the number of vowels and consonants in S in variables V and C respectively.
  • If the value of V is not equal to C or C is not equal to (V + 1), then print 0. Otherwise, performing the following steps:
    • Initialize denominator as 1.
    • Traverse the string S using the variable i and update the denominator as denominator*((count[S[i]])!).
    • Initialize numerator to V!*C!, and update the value of answer as numerator/denominator.
  • After completing the above steps, print the value of the answer as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
 
#define ll long long
#define mod 1000000007
#define N 1000001
using namespace std;
 
// Function to compute factorials till N
void Precomputefact(unordered_map<ll, ll>& fac)
{
    ll ans = 1;
 
    // Iterate in the range [1, N]
    for (ll i = 1; i <= N; i++) {
 
        // Update ans to ans*i
        ans = (ans * i) % mod;
 
        // Store the value of ans
        // in fac[i]
        fac[i] = ans;
    }
    return;
}
 
// Function to check whether the
// current character is a vowel or not
bool isVowel(char a)
{
    if (a == 'A' || a == 'E' || a == 'I' || a == 'O'
        || a == 'U')
        return true;
    else
        return false;
}
 
// Function to count the number of
// anagrams of S satisfying the
// given condition
void countAnagrams(string s, int n)
{
    // Store the factorials upto N
    unordered_map<ll, ll> fac;
 
    // Function Call to generate
    // all factorials upto n
    Precomputefact(fac);
 
    // Create a hashmap to store
    // frequencies of all characters
    unordered_map<char, ll> count;
 
    // Store the count of
    // vowels and consonants
    int vo = 0, co = 0;
 
    // Iterate through all
    // characters in the string
    for (int i = 0; i < n; i++) {
 
        // Update the frequency
        // of current character
        count[s[i]]++;
 
        // Check if the character
        // is vowel or consonant
        if (isVowel(s[i]))
            vo++;
        else
            co++;
    }
 
    // Check if ΣC==ΣV+1 or ΣC==ΣV
    if ((co == vo + 1) || (co == vo)) {
 
        // Store the denominator
        ll deno = 1;
 
        // Calculate the denominator
        // of the expression
        for (auto c : count) {
 
            // Multiply denominator by factorial
            // of counts of all letters
            deno = (deno * fac[c.second]) % mod;
        }
 
        // Store the numerator
        ll nume = fac[co] % mod;
        nume = (nume * fac[vo]) % mod;
 
        // Store the answer by dividing
        // numerator by denominator
        ll ans = nume / deno;
 
        // Print the answer
        cout << ans;
    }
 
    // Otherwise, print 0
    else {
        cout << 0;
    }
}
 
// Driver Code
int main()
{
    string S = "GADO";
    int l = S.size();
    countAnagrams(S, l);
 
    return 0;
}

Python3




# Python 3 program for the above approach
#include <bits/stdc++.h>
 
mod = 1000000007
N = 1000001
 
fac = {}
 
# Function to compute factorials till N
def Precomputefact():
    global fac
    ans = 1
 
    # Iterate in the range [1, N]
    for i in range(1,N+1,1):
        # Update ans to ans*i
        ans = (ans * i) % mod
 
        # Store the value of ans
        # in fac[i]
        fac[i] = ans
 
    return
 
# Function to check whether the
# current character is a vowel or not
def isVowel(a):
    if (a == 'A' or a == 'E' or a == 'I' or a == 'O' or a == 'U'):
        return True
    else:
        return False
 
# Function to count the number of
# anagrams of S satisfying the
# given condition
def countAnagrams(s,n):
    # Store the factorials upto N
    global fac
 
    # Function Call to generate
    # all factorials upto n
    Precomputefact()
 
    # Create a hashmap to store
    # frequencies of all characters
    count = {}
 
    # Store the count of
    # vowels and consonants
    vo = 0
    co = 0
 
    # Iterate through all
    # characters in the string
    for i in range(n):
        # Update the frequency
        # of current character
        if s[i] in count:
            count[s[i]] += 1
        else:
            count[s[i]] = 1
 
        # Check if the character
        # is vowel or consonant
        if (isVowel(s[i])):
            vo += 1
        else:
            co += 1
 
    # Check if ΣC==ΣV+1 or ΣC==ΣV
    if ((co == vo + 1) or (co == vo)):
        # Store the denominator
        deno = 1
 
        # Calculate the denominator
        # of the expression
        for key,value in count.items():
            # Multiply denominator by factorial
            # of counts of all letters
            deno = (deno * fac[value]) % mod
 
        # Store the numerator
        nume = fac[co] % mod
        nume = (nume * fac[vo]) % mod
 
        # Store the answer by dividing
        # numerator by denominator
        ans = nume // deno
 
        # Print the answer
        print(ans)
 
    # Otherwise, print 0
    else:
        print(0)
 
# Driver Code
if __name__ == '__main__':
    S = "GADO"
    l = len(S)
    countAnagrams(S, l)
     
    # This code is contributed by ipg2016107.

 
 

Output: 
4

 

 

Time Complexity: O(N)
Auxiliary Space: O(N)

 




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!