Count substrings of a given string whose anagram is a palindrome

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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


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.




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.