Skip to content
Related Articles

Related Articles

Improve Article

Count substrings of a given string whose anagram is a palindrome

  • Difficulty Level : Hard
  • Last Updated : 31 May, 2021

Given a string S of length N containing only lowercase alphabets, the task is to print the count of substrings of the given string whose anagram is palindromic.

Examples:

Input: S = “aaaa”
Output: 10
Explanation:
Possible substrings are {“a”, “a”, “a”, “a”, “aa”, “aa”, “aa”, “aaa”, “aaa”, “aaaa”}. Since all substrings are have palindromic anagrams, the required answer is 10.

Input: S = “abc”
Output: 3

Naive Approach: The idea is to generate all substrings of the given string and for each substring, check whether its anagram is a palindrome or not. Keep increasing the count of substrings for which the above condition is found to be true. Finally, print the count of all such substrings. 
Time Complexity: O(N3)
Auxiliary Space: O(N)

Bit Masking Approach: The idea is to generate the masks of 26-bit numbers as there are 26 characters. Also, observe that if the anagram of some string is a palindrome, then the frequencies of its characters except at most one character must be even. 
Follow the steps below to solve the problem:



  • Traverse the string and initialize a variable X = 0 at each index.
  • From every ithe index, traverse the string over a range of indices [i, N – 1], and for each character S[j], calculate Bitwise XOR of X and 2(S[j] – ‘a’), where 0th bit represents if the frequency of a is odd, 1st bit represents if the frequency of b is odd, and so on.
  • Then, check if X & (X – 1) is equal to 0 or not. If found to be true, then increment the count by 1
     

Illustration: 
Suppose, X = (0001000)2 
=> (X – 1) will be represented as (0000111)2
Therefore, X & (X – 1) = 0

  • Once the above steps are exhausted, print the count obtained.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to print count of substrings
// whose anagrams are palindromic
void countSubstring(string s)
{
    // Stores the answer
    int res = 0;
 
    // Iterate over the string
    for (int i = 0;
         i < s.length(); i++) {
 
        int x = 0;
 
        for (int j = i;
             j < s.length(); j++) {
 
            // Set the current character
            int temp = 1 << s[j] - 'a';
 
            // Parity update
            x ^= temp;
            if ((x & (x - 1)) == 0)
                res++;
        }
    }
 
    // Print the final count
    cout << res;
}
 
// Driver Code
int main()
{
    string str = "aaa";
 
    // Function Call
    countSubstring(str);
 
    return 0;
}

Java




// Java program for
// the above approach
class GFG{
 
// Function to print count of subStrings
// whose anagrams are palindromic
static void countSubString(String s)
{
  // Stores the answer
  int res = 0;
 
  // Iterate over the String
  for (int i = 0; i < s.length(); i++)
  {
    int x = 0;
    for (int j = i; j < s.length(); j++)
    {
      // Set the current character
      int temp = 1 << s.charAt(j) - 'a';
 
      // Parity update
      x ^= temp;
      if ((x & (x - 1)) == 0)
        res++;
    }
  }
 
  // Print the final count
  System.out.print(res);
}
 
// Driver Code
public static void main(String[] args)
{
  String str = "aaa";
 
  // Function Call
  countSubString(str);
}
}
 
// This code is contributed by shikhasingrajput

Python3




# Python3 program for
# the above approach
 
# Function to prcount of subStrings
# whose anagrams are palindromic
def countSubString(s):
   
    # Stores the answer
    res = 0;
 
    # Iterate over the String
    for i in range(len(s)):
        x = 0;
        for j in range(i, len(s)):
           
            # Set the current character
            temp = 1 << ord(s[j]) - ord('a');
 
            # Parity update
            x ^= temp;
            if ((x & (x - 1)) == 0):
                res += 1;
 
    # Print final count
    print(res);
 
# Driver Code
if __name__ == '__main__':
    str = "aaa";
 
    # Function Call
    countSubString(str);
 
# This code is contributed by 29AjayKumar

C#




// C# program for
// the above approach
using System;
class GFG{
 
// Function to print count of subStrings
// whose anagrams are palindromic
static void countSubString(String s)
{
  // Stores the answer
  int res = 0;
 
  // Iterate over the String
  for (int i = 0; i < s.Length; i++)
  {
    int x = 0;
 
    for (int j = i; j < s.Length; j++)
    {
      // Set the current character
      int temp = 1 << s[j] - 'a';
 
      // Parity update
      x ^= temp;
      if ((x & (x - 1)) == 0)
        res++;
    }
  }
 
  // Print the readonly count
  Console.Write(res);
}
 
// Driver Code
public static void Main(String[] args)
{
  String str = "aaa";
 
  // Function Call
  countSubString(str);
}
}
 
// This code is contributed by shikhasingrajput

Javascript




<script>
 
// JavaScript  program for
//the above approach
 
// Function to prlet count of subStrings
// whose anagrams are palindromic
function countSubString(s)
{
  // Stores the answer
  let res = 0;
  
  // Iterate over the String
  for (let i = 0; i < s.length; i++)
  {
    let x = 0;
    for (let j = i; j < s.length; j++)
    {
      // Set the current character
      let temp = 1 << s[j] - 'a';
  
      // Parity update
      x ^= temp;
      if ((x & (x - 1)) == 0)
        res++;
    }
  }
  
  // Prlet the final count
  document.write(res);
}
  
     
// Driver Code
 
    let str = "aaa";
  
  // Function Call
  countSubString(str);
   
  // This code is contributed by souravghosh0416.
</script>
Output
6

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

Efficient Approach: To optimize the above Bit Masking technique, the idea is to use a Map. Follow the steps below to solve the problem: 

  1. Initialize a map to store the frequencies of the masks. Initialize a variable X = 0.
  2. Traverse the string and for every ith index, calculate Bitwise XOR of X and 2(S[j] – ‘a’) and update the answer by adding the frequency of the current value of X in the Map because if any substring from 0 to j has the same mask as that of X, which is a mask for substring from 0 to i, then substring S[j + 1, i] will have even frequencies, where j < i.
  3. Also add the frequencies of masks X xor 2k, where, 0 ≤ k < 26. After that, increment the frequency of X by 1.
  4. Repeat the above steps for each index of the given string.
  5. After traversing the given string, print the required answer.

Below is the implementation of the above approach: 

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to get the count of substrings
// whose anagrams are palindromic
void countSubstring(string s)
{
    // Store the answer
    int answer = 0;
 
    // Map to store the freq of masks
    unordered_map<int, int> m;
 
    // Set frequency for mask
    // 00...00 to 1
    m[0] = 1;
 
    // Store mask in x from 0 to i
    int x = 0;
    for (int j = 0; j < s.length(); j++) {
        x ^= 1 << (s[j] - 'a');
 
        // Update answer
        answer += m[x];
        for (int i = 0; i < 26; ++i) {
            answer += m[x ^ (1 << i)];
        }
 
        // Update frequency
        m[x] += 1;
    }
 
    // Print the answer
    cout << answer;
}
 
// Driver Code
int main()
{
    string str = "abab";
 
    // Function Call
    countSubstring(str);
    return 0;
}

Java




// Java program for
// the above approach
import java.util.*;
class GFG {
 
// Function to get the count of subStrings
// whose anagrams are palindromic
static void countSubString(String s)
{
  // Store the answer
  int answer = 0;
 
  // Map to store the freq of masks
  HashMap<Integer,
          Integer> m = new HashMap<Integer,
                                   Integer>();
   
  // Set frequency for mask
  // 00...00 to 1
  m.put(0, 1);
 
  // Store mask in x from 0 to i
  int x = 0;
  for (int j = 0; j < s.length(); j++)
  {
    x ^= 1 << (s.charAt(j) - 'a');
 
    // Update answer
    answer += m.containsKey(x) ? m.get(x) : 0;
    for (int i = 0; i < 26; ++i)
    {
      answer += m.containsKey(x ^ (1 << i)) ?
                m.get(x ^ (1 << i)) : 0;
    }
 
    // Update frequency
    if (m.containsKey(x))
      m.put(x, m.get(x) + 1);
    else
      m.put(x, 1);
  }
 
  // Print the answer
  System.out.print(answer);
}
 
// Driver Code
public static void main(String[] args)
{
  String str = "abab";
 
  // Function Call
  countSubString(str);
}
}
 
// This code is contributed by shikhasingrajput

Python3




# Python3 program for the above approach
from collections import defaultdict
 
# Function to get the count of substrings
# whose anagrams are palindromic
def countSubstring(s):
 
    # Store the answer
    answer = 0
 
    # Map to store the freq of masks
    m = defaultdict(lambda : 0)
 
    # Set frequency for mask
    # 00...00 to 1
    m[0] = 1
 
    # Store mask in x from 0 to i
    x = 0
     
    for j in range(len(s)):
        x ^= 1 << (ord(s[j]) - ord('a'))
 
        # Update answer
        answer += m[x]
        for i in range(26):
            answer += m[x ^ (1 << i)]
 
        # Update frequency
        m[x] += 1
 
    # Print the answer
    print(answer)
 
# Driver Code
str = "abab"
 
# Function call
countSubstring(str)
 
# This code is contributed by Shivam Singh

C#




// C# program for
// the above approach
using System;
using System.Collections.Generic;
class GFG{
 
// Function to get the count of
// subStrings whose anagrams
// are palindromic
static void countSubString(String s)
{
  // Store the answer
  int answer = 0;
 
  // Map to store the freq of masks
  Dictionary<int,
             int> m = new Dictionary<int,
                                     int>();
   
  // Set frequency for mask
  // 00...00 to 1
  m.Add(0, 1);
 
  // Store mask in x from 0 to i
  int x = 0;
  for (int j = 0; j < s.Length; j++)
  {
    x ^= 1 << (s[j] - 'a');
 
    // Update answer
    answer += m.ContainsKey(x) ? m[x] : 0;
    for (int i = 0; i < 26; ++i)
    {
      answer += m.ContainsKey(x ^ (1 << i)) ?
                m[x ^ (1 << i)] : 0;
    }
 
    // Update frequency
    if (m.ContainsKey(x))
      m[x] = m[x] + 1;
    else
      m.Add(x, 1);
  }
 
  // Print the answer
  Console.Write(answer);
}
 
// Driver Code
public static void Main(String[] args)
{
  String str = "abab";
 
  // Function Call
  countSubString(str);
}
}
 
// This code is contributed by shikhasingrajput

Javascript




<script>
 
// JavaScript program for the above approach
 
// Function to get the count of substrings
// whose anagrams are palindromic
function countSubstring(s)
{
    // Store the answer
    var answer = 0;
 
    // Map to store the freq of masks
    var m = new Map();
 
    // Set frequency for mask
    // 00...00 to 1
    m.set(0, 1);
 
    // Store mask in x from 0 to i
    var x = 0;
    for (var j = 0; j < s.length; j++) {
        x ^= 1 << (s[j].charCodeAt(0) - 'a'.charCodeAt(0));
 
        // Update answer
        answer += m.has(x)? m.get(x):0;
        for (var i = 0; i < 26; ++i) {
            answer += m.has(x ^ (1 << i))?m.get(x ^ (1 << i)):0;
        }
 
        // Update frequency
        if(m.has(x))
            m.set(x, m.get(x)+1)
        else
            m.set(x, 1)
    }
 
    // Print the answer
    document.write( answer);
}
 
// Driver Code
var str = "abab";
 
// Function Call
countSubstring(str);
 
 
</script>
Output
7

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

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.




My Personal Notes arrow_drop_up
Recommended Articles
Page :