Count Occurrences of Anagrams
Given a word and a text, return the count of the occurrences of anagrams of the word in the text(For eg: anagrams of word for are for, ofr, rof etc.))
Examples:
Input : forxxorfxdofr
for
Output : 3
Explanation : Anagrams of the word for – for, orf, ofr appear in the text and hence the count is 3.
Input : aabaabaa
aaba
Output : 4
Explanation : Anagrams of the word aaba – aaba, abaa each appear twice in the text and hence the count is 4.
A simple approach is to traverse from start of the string considering substrings of length equal to the length of the given word and then check if this substring has all the characters of word.
Implementation:
C++
#include<bits/stdc++.h>
using namespace std;
bool areAnagram(string s1, string s2)
{
map< char , int > m;
for ( int i = 0; i < s1.length(); i++)
m[s1[i]]++;
for ( int i = 0; i < s2.length(); i++)
m[s2[i]]--;
for ( auto it = m.begin(); it != m.end(); it++)
if (it -> second != 0)
return false ;
return true ;
}
int countAnagrams(string text, string word)
{
int res = 0;
for ( int i = 0;
i < text.length() - word.length() + 1;
i++)
{
if (areAnagram(text.substr(i, word.length()),
word))
res++;
}
return res;
}
int main()
{
string text = "forxxorfxdofr" ;
string word = "for" ;
cout << countAnagrams(text, word);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
public class GFG {
static boolean araAnagram(String s1,
String s2)
{
char [] ch1 = s1.toCharArray();
char [] ch2 = s2.toCharArray();
Arrays.sort(ch1);
Arrays.sort(ch2);
if (Arrays.equals(ch1, ch2))
return true ;
else
return false ;
}
static int countAnagrams(String text, String word)
{
int N = text.length();
int n = word.length();
int res = 0 ;
for ( int i = 0 ; i <= N - n; i++) {
String s = text.substring(i, i + n);
if (araAnagram(word, s))
res++;
}
return res;
}
public static void main(String args[])
{
String text = "forxxorfxdofr" ;
String word = "for" ;
System.out.print(countAnagrams(text, word));
}
}
|
Python3
def areAnagram(s1, s2):
m = {}
for i in range ( len (s1)):
if s1[i] not in m:
m[s1[i]] = 1
else :
cnt = m[s1[i]]
m.pop(s1[i])
m[s1[i]] = cnt + 1
for j in range ( len (s2)):
if ((s2[j] in m) = = False ):
return False
else :
cnt = m[s2[j]]
m.pop(s2[j])
m[s2[j]] = cnt - 1
for it in m.values():
if (it ! = 0 ):
return False
return True
def countAnagrams(text, word):
res = 0
for i in range ( len (text) - len (word) + 1 ):
if (areAnagram(text[i:i + len (word)], word)):
res + = 1
return res
text = "forxxorfxdofr"
word = "for"
print (countAnagrams(text, word))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static bool areAnagram( string first, string second)
{
if (first.Length != second.Length)
return false ;
if (first == second)
return true ;
Dictionary< char , int > pool
= new Dictionary< char , int >();
foreach (
char element in first
.ToCharArray())
{
if (pool.ContainsKey(element))
pool[element]++;
else
pool.Add(element, 1);
}
foreach ( char element in second
.ToCharArray())
{
if (!pool.ContainsKey(
element))
return false ;
if (--pool[element]
== 0)
pool.Remove(element);
}
return pool.Count == 0;
}
static int countAnagrams( string text, string word)
{
int N = text.Length;
int n = word.Length;
int res = 0;
for ( int i = 0; i <= N - n; i++) {
string s = text.Substring(i, n);
if (areAnagram(word, s) == true ) {
res++;
}
}
return res;
}
public static void Main()
{
string text = "forxxorfxdofr" ;
string word = "for" ;
Console.Write(countAnagrams(text, word));
}
}
|
Javascript
<script>
function areAnagram(s1, s2)
{
let m = new Map();
for (let i = 0; i < s1.length ; i++)
{
if (m.has(s1[i])=== false ){
m.set(s1[i],1)
}
else {
let cnt = m.get(s1[i]);
m. delete (s1[i]);
m.set(s1[i],cnt+1);
}
}
for (let j = 0; j < s1.length; j++)
{
if (m.has(s2[j])=== false ){
return false ;
}
else {
let cnt = m.get(s2[j]);
m. delete (s2[j]);
m.set(s2[j],cnt-1);
}
}
for (const it in m.values()){
if (it !== 0) return false
}
return true ;
}
function countAnagrams(text, word)
{
let res = 0;
for (let i = 0;i < text.length - word.length + 1;i++)
{
if (areAnagram(text.substring(i, i+word.length), word)) res++;
}
return res;
}
let text = "forxxorfxdofr" ;
let word = "for" ;
document.write(countAnagrams(text, word));
</script>
|
Complexity Analysis:
- Time Complexity: O(l1logl1 + l2logl2)
- Auxiliary space: O(l1 + l2).
An Efficient Solution is to use a count array to check for anagrams, we can construct the current count window from the previous window in O(1) time using the sliding window concept.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public :
static int findAnagrams( const std::string& text,
const std::string& word)
{
int text_length = text.length();
int word_length = word.length();
if (text_length < 0 || word_length < 0
|| text_length < word_length)
return 0;
constexpr int CHARACTERS = 256;
int count = 0;
int index = 0;
std::array< char , CHARACTERS> wordArr;
wordArr.fill(0);
std::array< char , CHARACTERS> textArr;
textArr.fill(0);
for (; index < word_length; index++) {
wordArr[CHARACTERS - word[index]]++;
textArr[CHARACTERS - text[index]]++;
}
if (wordArr == textArr)
count += 1;
for (; index < text_length; index++) {
textArr[CHARACTERS - text[index]]++;
textArr[CHARACTERS
- text[index - word_length]]--;
if (wordArr == textArr)
count += 1;
}
return count;
}
};
int main()
{
const std::string& text = "forxxorfxdofr" ;
const std::string& word = "for" ;
cout << Solution::findAnagrams(text, word);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class Solution {
public static int countAnagrams(String s, String p)
{
int CHARACTERS = 256 ;
int sn = s.length();
int pn = p.length();
int count = 0 ;
if (sn < 0 || pn < 0 || sn < pn)
return 0 ;
char [] pArr = new char [CHARACTERS];
char [] sArr = new char [CHARACTERS];
int i = 0 ;
for (; i < pn; i++) {
sArr[CHARACTERS - s.charAt(i)]++;
pArr[CHARACTERS - p.charAt(i)]++;
}
if (Arrays.equals(pArr, sArr))
count += 1 ;
for (; i < sn; i++) {
sArr[CHARACTERS - s.charAt(i)]++;
sArr[CHARACTERS - s.charAt(i - pn)]--;
if (Arrays.equals(pArr, sArr))
count += 1 ;
}
return count;
}
public static void main(String args[])
{
String text = "forxxorfxdofr" ;
String word = "for" ;
System.out.print(countAnagrams(text, word));
}
}
|
Python3
string = "forxxorfxdofr"
ptr = "for"
n = len (string)
k = len (ptr)
d = {}
for i in ptr:
if i in d:
d[i] + = 1
else :
d[i] = 1
i = 0
j = 0
count = len (d)
ans = 0
while j < n:
if string[j] in d:
d[string[j]] - = 1
if d[string[j]] = = 0 :
count - = 1
if (j - i + 1 ) < k:
j + = 1
elif (j - i + 1 ) = = k:
if count = = 0 :
ans + = 1
if string[i] in d:
d[string[i]] + = 1
if d[string[i]] = = 1 :
count + = 1
i + = 1
j + = 1
print (ans)
|
C#
using System;
using System.Linq;
class Solution
{
public static int FindAnagrams( string text, string word)
{
int textLength = text.Length;
int wordLength = word.Length;
if (textLength < 0 || wordLength < 0 || textLength < wordLength)
return 0;
const int CHARACTERS = 256;
int count = 0;
int index = 0;
char [] wordArr = new char [CHARACTERS];
Array.Fill(wordArr, ( char )0);
char [] textArr = new char [CHARACTERS];
Array.Fill(textArr, ( char )0);
for (; index < wordLength; index++)
{
wordArr[CHARACTERS - word[index]]++;
textArr[CHARACTERS - text[index]]++;
}
if (wordArr.SequenceEqual(textArr))
count += 1;
for (; index < textLength; index++)
{
textArr[CHARACTERS - text[index]]++;
textArr[CHARACTERS - text[index - wordLength]]--;
if (wordArr.SequenceEqual(textArr))
count += 1;
}
return count;
}
}
class Program
{
static void Main( string [] args)
{
string text = "forxxorfxdofr" ;
string word = "for" ;
Console.WriteLine(Solution.FindAnagrams(text, word));
}
}
|
Javascript
<script>
let string = "forxxorfxdofr"
let ptr = "for"
let n = string.length
let k = ptr.length
let temp = []
let d = new Map();
for (let i = 0; i < ptr.length; i++)
{
if (d.has(ptr[i]))
d.set(ptr[i], d.get(ptr[i])+1)
else
d.set(ptr[i], 1)
}
let i = 0
let j = 0
let count = d.size
let ans = 0
while (j < n)
{
if (d.has(string[j]))
{
d.set(string[j], d.get(string[j]) - 1)
if (d.get(string[j]) == 0)
count--
}
if (j - i + 1 < k)
j++
else if (j - i + 1 == k){
if (count == 0)
ans++
if (d.has(string[i]))
{
d.set(string[i],d.get(string[i])+1)
if (d.get(string[i]) == 1)
count++
}
i++
j++
}
}
document.write(ans)
</script>
|
Complexity Analysis:
- Time Complexity: O(l1 + l2)
- Auxiliary space: O(l1 + l2).
Another Approach:
- Create an empty frequency map of characters in the word we are looking for.
- Populate the frequency map created in step 1 with the frequency of each character in the word we are looking for.
- Initialize a frequency map for the current window of characters in the text.
- Initialize a count variable to keep track of the number of anagrams found.
- Use a sliding window approach to iterate over the text.
- At each iteration, add the current character to the frequency map for the window and remove the character that went out of the window.
- Compare the frequency maps of the word and the window to check if they are equal.
- If the frequency maps are equal, increment the count of anagrams found.
- Return the count of anagrams found.
Below is the implementation of the above approach:
C++
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
int countAnagrams(string text, string word)
{
int n = text.size(), m = word.size();
unordered_map< char , int > freqWord, freqText;
int count = 0;
for ( char c : word)
freqWord++;
for ( int i = 0; i < n; i++) {
freqText]++;
if (i >= m) {
if (freqText] == 1)
freqText.erase(text[i - m]);
else
freqText]--;
}
if (i >= m - 1 && freqText == freqWord)
count++;
}
return count;
}
int main()
{
string text = "forxxorfxdofr" ;
string word = "for" ;
cout << countAnagrams(text, word) << endl;
return 0;
}
|
Java
import java.util.HashMap;
import java.util.Map;
public class Main {
public static int countAnagrams(String text, String word) {
int n = text.length();
int m = word.length();
Map<Character, Integer> freqWord = new HashMap<>();
Map<Character, Integer> freqText = new HashMap<>();
int count = 0 ;
for ( char c : word.toCharArray()) {
freqWord.put(c, freqWord.getOrDefault(c, 0 ) + 1 );
}
for ( int i = 0 ; i < n; i++) {
char currentChar = text.charAt(i);
freqText.put(currentChar, freqText.getOrDefault(currentChar, 0 ) + 1 );
if (i >= m) {
char removedChar = text.charAt(i - m);
if (freqText.get(removedChar) == 1 ) {
freqText.remove(removedChar);
} else {
freqText.put(removedChar, freqText.get(removedChar) - 1 );
}
}
if (i >= m - 1 && freqText.equals(freqWord)) {
count++;
}
}
return count;
}
public static void main(String[] args) {
String text = "forxxorfxdofr" ;
String word = "for" ;
System.out.println(countAnagrams(text, word));
}
}
|
Python3
def countAnagrams(text, word):
n = len (text)
m = len (word)
freqWord = {}
freqText = {}
count = 0
for c in word:
freqWord = freqWord.get(c, 0 ) + 1
for i in range (n):
freqText] = freqText.get(text[i], 0 ) + 1
if i > = m:
if freqText] = = 1 :
del freqText]
else :
freqText] - = 1
if i > = m - 1 and freqText = = freqWord:
count + = 1
return count
text = "forxxorfxdofr"
word = "for"
print (countAnagrams(text, word))
|
C#
using System;
using System.Collections.Generic;
class Program
{
static int CountAnagrams( string text, string word)
{
int n = text.Length;
int m = word.Length;
Dictionary< char , int > freqWord = new Dictionary< char , int >();
Dictionary< char , int > freqText = new Dictionary< char , int >();
int count = 0;
foreach ( char c in word)
{
if (freqWord.ContainsKey(c))
freqWord++;
else
freqWord = 1;
}
for ( int i = 0; i < n; i++)
{
if (freqText.ContainsKey(text[i]))
freqText]++;
else
freqText] = 1;
if (i >= m)
{
char charToRemove = text[i - m];
if (freqText[charToRemove] == 1)
freqText.Remove(charToRemove);
else
freqText[charToRemove]--;
}
if (i >= m - 1 && AreDictionariesEqual(freqText, freqWord))
count++;
}
return count;
}
static bool AreDictionariesEqual(Dictionary< char , int > dict1, Dictionary< char , int > dict2)
{
if (dict1.Count != dict2.Count)
return false ;
foreach ( var kvp in dict1)
{
char key = kvp.Key;
int value = kvp.Value;
if (!dict2.ContainsKey(key) || dict2[key] != value)
return false ;
}
return true ;
}
static void Main()
{
string text = "forxxorfxdofr" ;
string word = "for" ;
Console.WriteLine(CountAnagrams(text, word));
}
}
|
Javascript
function countAnagrams(text, word) {
const n = text.length;
const m = word.length;
const freqWord = new Map();
const freqText = new Map();
let count = 0;
for (const c of word) {
freqWord.set(c, (freqWord.get(c) || 0) + 1);
}
for (let i = 0; i < n; i++) {
freqText.set(text[i], (freqText.get(text[i]) || 0) + 1);
if (i >= m) {
const prevChar = text[i - m];
const prevFreq = freqText.get(prevChar);
if (prevFreq === 1) {
freqText. delete (prevChar);
} else {
freqText.set(prevChar, prevFreq - 1);
}
}
if (i >= m - 1 && compareMaps(freqText, freqWord)) {
count++;
}
}
return count;
}
function compareMaps(map1, map2) {
if (map1.size !== map2.size) {
return false ;
}
for (const [key, value] of map1) {
if (value !== map2.get(key)) {
return false ;
}
}
return true ;
}
const text = "forxxorfxdofr" ;
const word = "for" ;
console.log(countAnagrams(text, word));
|
Time Complexity: O(n), where n is the length of the text. This is because we only iterate over the text once and use constant time operations for each iteration.
Auxiliary Space: O(k), where k is the size of the frequency map of the word. This is because we only need to store the frequency maps of the word and the window at any given time.
Please suggest if someone has a better solution that is more efficient in terms of space and time.
This article is contributed by Aarti_Rathi.
Last Updated :
02 Dec, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...