Count substrings of a given string whose anagram is a palindrome
Last Updated :
02 Feb, 2022
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++
#include <bits/stdc++.h>
using namespace std;
void countSubstring(string s)
{
int res = 0;
for ( int i = 0;
i < s.length(); i++) {
int x = 0;
for ( int j = i;
j < s.length(); j++) {
int temp = 1 << s[j] - 'a' ;
x ^= temp;
if ((x & (x - 1)) == 0)
res++;
}
}
cout << res;
}
int main()
{
string str = "aaa" ;
countSubstring(str);
return 0;
}
|
Java
class GFG{
static void countSubString(String s)
{
int res = 0 ;
for ( int i = 0 ; i < s.length(); i++)
{
int x = 0 ;
for ( int j = i; j < s.length(); j++)
{
int temp = 1 << s.charAt(j) - 'a' ;
x ^= temp;
if ((x & (x - 1 )) == 0 )
res++;
}
}
System.out.print(res);
}
public static void main(String[] args)
{
String str = "aaa" ;
countSubString(str);
}
}
|
Python3
def countSubString(s):
res = 0 ;
for i in range ( len (s)):
x = 0 ;
for j in range (i, len (s)):
temp = 1 << ord (s[j]) - ord ( 'a' );
x ^ = temp;
if ((x & (x - 1 )) = = 0 ):
res + = 1 ;
print (res);
if __name__ = = '__main__' :
str = "aaa" ;
countSubString( str );
|
C#
using System;
class GFG{
static void countSubString(String s)
{
int res = 0;
for ( int i = 0; i < s.Length; i++)
{
int x = 0;
for ( int j = i; j < s.Length; j++)
{
int temp = 1 << s[j] - 'a' ;
x ^= temp;
if ((x & (x - 1)) == 0)
res++;
}
}
Console.Write(res);
}
public static void Main(String[] args)
{
String str = "aaa" ;
countSubString(str);
}
}
|
Javascript
<script>
function countSubString(s)
{
let res = 0;
for (let i = 0; i < s.length; i++)
{
let x = 0;
for (let j = i; j < s.length; j++)
{
let temp = 1 << s[j] - 'a' ;
x ^= temp;
if ((x & (x - 1)) == 0)
res++;
}
}
document.write(res);
}
let str = "aaa" ;
countSubString(str);
</script>
|
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:
- Initialize a map to store the frequencies of the masks. Initialize a variable X = 0.
- 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.
- Also add the frequencies of masks X xor 2k, where, 0 ? k < 26. After that, increment the frequency of X by 1.
- Repeat the above steps for each index of the given string.
- After traversing the given string, print the required answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void countSubstring(string s)
{
int answer = 0;
unordered_map< int , int > m;
m[0] = 1;
int x = 0;
for ( int j = 0; j < s.length(); j++) {
x ^= 1 << (s[j] - 'a' );
answer += m[x];
for ( int i = 0; i < 26; ++i) {
answer += m[x ^ (1 << i)];
}
m[x] += 1;
}
cout << answer;
}
int main()
{
string str = "abab" ;
countSubstring(str);
return 0;
}
|
Java
import java.util.*;
class GFG {
static void countSubString(String s)
{
int answer = 0 ;
HashMap<Integer,
Integer> m = new HashMap<Integer,
Integer>();
m.put( 0 , 1 );
int x = 0 ;
for ( int j = 0 ; j < s.length(); j++)
{
x ^= 1 << (s.charAt(j) - 'a' );
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 ;
}
if (m.containsKey(x))
m.put(x, m.get(x) + 1 );
else
m.put(x, 1 );
}
System.out.print(answer);
}
public static void main(String[] args)
{
String str = "abab" ;
countSubString(str);
}
}
|
Python3
from collections import defaultdict
def countSubstring(s):
answer = 0
m = defaultdict( lambda : 0 )
m[ 0 ] = 1
x = 0
for j in range ( len (s)):
x ^ = 1 << ( ord (s[j]) - ord ( 'a' ))
answer + = m[x]
for i in range ( 26 ):
answer + = m[x ^ ( 1 << i)]
m[x] + = 1
print (answer)
str = "abab"
countSubstring( str )
|
C#
using System;
using System.Collections.Generic;
class GFG{
static void countSubString(String s)
{
int answer = 0;
Dictionary< int ,
int > m = new Dictionary< int ,
int >();
m.Add(0, 1);
int x = 0;
for ( int j = 0; j < s.Length; j++)
{
x ^= 1 << (s[j] - 'a' );
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;
}
if (m.ContainsKey(x))
m[x] = m[x] + 1;
else
m.Add(x, 1);
}
Console.Write(answer);
}
public static void Main(String[] args)
{
String str = "abab" ;
countSubString(str);
}
}
|
Javascript
<script>
function countSubstring(s)
{
var answer = 0;
var m = new Map();
m.set(0, 1);
var x = 0;
for ( var j = 0; j < s.length; j++) {
x ^= 1 << (s[j].charCodeAt(0) - 'a' .charCodeAt(0));
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;
}
if (m.has(x))
m.set(x, m.get(x)+1)
else
m.set(x, 1)
}
document.write( answer);
}
var str = "abab" ;
countSubstring(str);
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...