Count of total anagram substrings

Last Updated : 20 Feb, 2026

Given a string s consisting of only lowercase alphabet characters, count all pairs of substrings of s that are anagrams of each other.

Examples:

Input: s = "xyyx"
Output: 4
Explanation: Total anagrammatic substring pairs are: ["x", "x"], ["y", "y"], ["xy", "yx"], ["xyy", "yyx"]

Input: s = "geeg"
Output: 4
Explanation: Valid anagrammatic substring pairs are: ["g", "g"], ["e", "e"], ["gee", "eeg"], ["ge", "eg"]

Input: s = "aba"
Output: 2
Explanation: Anagrammatic substring pairs include: ["a", "a"], ["ab", "ba"]

[Naive Approach] Generate all substrings and Compare - O(n^5 log n) Time and O(n^3) Space

Generate all possible substrings of the given string and store them. Then compare every pair of substrings and check whether they are anagrams by sorting both strings. If two sorted substrings are equal, increment the count of anagrammatic pairs.

C++
#include <iostream>
using namespace std;

bool isAnagram(string a, string b) {
    if (a.length() != b.length())
        return false;

    sort(a.begin(), a.end());
    sort(b.begin(), b.end());

    return a == b;
}

int countAnagramPairs(string s) {
    int n = s.length();
    vector<string> substrings;

    // Step 1: Generate all substrings
    for (int i = 0; i < n; i++) {
        for (int len = 1; len <= n - i; len++) {
            substrings.push_back(s.substr(i, len));
        }
    }

    int count = 0;

    // Step 2: Compare every pair of substrings
    for (int i = 0; i < substrings.size(); i++) {
        for (int j = i + 1; j < substrings.size(); j++) {
            if (isAnagram(substrings[i], substrings[j])) {
                count++;
            }
        }
    }

    return count;
}

int main() {
    string s = "abba";
    cout << countAnagramPairs(s);
    return 0;
}
Java
import java.util.*;

public class GFG {

    // Function to check if two strings are anagrams
    static boolean isAnagram(String a, String b) {
        if (a.length() != b.length())
            return false;

        char[] arr1 = a.toCharArray();
        char[] arr2 = b.toCharArray();

        Arrays.sort(arr1);
        Arrays.sort(arr2);

        return Arrays.equals(arr1, arr2);
    }

    static int countAnagramPairs(String s) {
        int n = s.length();
        List<String> substrings = new ArrayList<>();

        // Step 1: Generate all substrings
        for (int i = 0; i < n; i++) {
            for (int len = 1; len <= n - i; len++) {
                substrings.add(s.substring(i, i + len));
            }
        }

        int count = 0;

        // Step 2: Compare every pair
        for (int i = 0; i < substrings.size(); i++) {
            for (int j = i + 1; j < substrings.size(); j++) {
                if (isAnagram(substrings.get(i), substrings.get(j))) {
                    count++;
                }
            }
        }

        return count;
    }

    public static void main(String[] args) {
        String s = "abba";
        System.out.println(countAnagramPairs(s));
    }
}
Python
def isAnagram(a, b):
    if len(a) != len(b):
        return False
    return sorted(a) == sorted(b)

def countAnagramPairs(s):
    n = len(s)
    substrings = []

    # Step 1: Generate all substrings
    for i in range(n):
        for length in range(1, n - i + 1):
            substrings.append(s[i:i+length])

    count = 0

    # Step 2: Compare every pair
    for i in range(len(substrings)):
        for j in range(i + 1, len(substrings)):
            if isAnagram(substrings[i], substrings[j]):
                count += 1

    return count

s = "abba"
print(countAnagramPairs(s))
C#
using System;
using System.Collections.Generic;
using System.Linq;

public class GFG
{
    static bool IsAnagram(string a, string b)
    {
        if (a.Length != b.Length)
            return false;

        var arr1 = a.ToCharArray();
        var arr2 = b.ToCharArray();

        Array.Sort(arr1);
        Array.Sort(arr2);

        return new string(arr1) == new string(arr2);
    }

    static int CountAnagramPairs(string s)
    {
        int n = s.Length;
        List<string> substrings = new List<string>();

        // Step 1: Generate all substrings
        for (int i = 0; i < n; i++)
        {
            for (int len = 1; len <= n - i; len++)
            {
                substrings.Add(s.Substring(i, len));
            }
        }

        int count = 0;

        // Step 2: Compare every pair
        for (int i = 0; i < substrings.Count; i++)
        {
            for (int j = i + 1; j < substrings.Count; j++)
            {
                if (IsAnagram(substrings[i], substrings[j]))
                {
                    count++;
                }
            }
        }

        return count;
    }

    public static void Main()
    {
        string s = "abba";
        Console.WriteLine(CountAnagramPairs(s));
    }
}
JavaScript
function isAnagram(a, b) {
    if (a.length !== b.length)
        return false;

    return a.split('').sort().join('') ===
           b.split('').sort().join('');
}

function countAnagramPairs(s) {
    let n = s.length;
    let substrings = [];

    // Step 1: Generate all substrings
    for (let i = 0; i < n; i++) {
        for (let len = 1; len <= n - i; len++) {
            substrings.push(s.substring(i, i + len));
        }
    }

    let count = 0;

    // Step 2: Compare every pair
    for (let i = 0; i < substrings.length; i++) {
        for (let j = i + 1; j < substrings.length; j++) {
            if (isAnagram(substrings[i], substrings[j])) {
                count++;
            }
        }
    }

    return count;
}

//Driver Code
let s = "abba";
console.log(countAnagramPairs(s));

Output
4

[Expected Approach 1] Sorted Substring Hashing - O(n^3 log n) Time and O(n^3) Space

The idea is to count pairs of substrings that are anagrams by exploiting the property that anagrams share the same sorted form. We generate all possible substrings, sort each substring, and store their frequencies in a map. If a sorted substring appears f times, then the number of valid anagrammatic pairs is f × (f - 1) / 2. This ensures we capture all unique anagram pairs efficiently using frequency counting.

C++
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;

int countAnagramPairs(string &s) {

    int n = s.length();
    int count = 0;

    // Map to store frequency of sorted substrings
    unordered_map<string, int> freqMap;

    // Generate all substrings
    for (int i = 0; i < n; i++) {
        string curr = "";

        for (int j = i; j < n; j++) {
            curr += s[j];

            // Sort characters of the current substring
            string sortedStr = curr;
            sort(sortedStr.begin(), sortedStr.end());

            // Increment count of this sorted pattern
            freqMap[sortedStr]++;
        }
    }

    // Count total anagrammatic pairs from frequencies
    for (auto &entry : freqMap) {
        int f = entry.second;

        // Choose any 2 from f => f * (f - 1) / 2
        if (f > 1) {
            count += (f * (f - 1)) / 2;
        }
    }

    return count;
}

int main() {

    string s = "xyyx";

    cout << countAnagramPairs(s);

    return 0;
}
Java
import java.util.*;

class GfG {

    public static int countAnagramPairs(String s) {

        int n = s.length();
        int count = 0;

        // Map to store frequency of sorted substrings
        HashMap<String, Integer> freqMap = new HashMap<>();

        // Generate all substrings
        for (int i = 0; i < n; i++) {
            String curr = "";

            for (int j = i; j < n; j++) {
                curr += s.charAt(j);

                // Sort characters of the current substring
                char[] chars = curr.toCharArray();
                Arrays.sort(chars);
                String sortedStr = new String(chars);

                // Increment count of this sorted pattern
                freqMap.put(sortedStr, freqMap.getOrDefault(sortedStr, 0) + 1);
            }
        }

        // Count total anagrammatic pairs from frequencies
        for (Map.Entry<String, Integer> entry : freqMap.entrySet()) {
            int f = entry.getValue();

            // Choose any 2 from f => f * (f - 1) / 2
            if (f > 1) {
                count += (f * (f - 1)) / 2;
            }
        }

        return count;
    }

    
    public static void main(String[] args) {
        String s = "xyyx";

        System.out.println(countAnagramPairs(s));
    }
}
Python
from collections import defaultdict

def countAnagramPairs(s):

    n = len(s)
    count = 0

    # Map to store frequency of sorted substrings
    freqMap = defaultdict(int)

    # Generate all substrings
    for i in range(n):
        curr = ""

        for j in range(i, n):
            curr += s[j]

            # Sort characters of the current substring
            sortedStr = ''.join(sorted(curr))

            # Increment count of this sorted pattern
            freqMap[sortedStr] += 1

    # Count total anagrammatic pairs from frequencies
    for f in freqMap.values():

        # Choose any 2 from f => f * (f - 1) / 2
        if f > 1:
            count += (f * (f - 1)) // 2

    return count
    
if __name__ == "__main__":

    s = "xyyx"

    print(countAnagramPairs(s))
C#
using System;
using System.Collections.Generic;

class GfG {

    public static int countAnagramPairs(string s) {

        int n = s.Length;
        int count = 0;

        // Map to store frequency of sorted substrings
        Dictionary<string, int> freqMap = new Dictionary<string, int>();

        // Generate all substrings
        for (int i = 0; i < n; i++) {
            string curr = "";

            for (int j = i; j < n; j++) {
                curr += s[j];

                // Sort characters of the current substring
                char[] chars = curr.ToCharArray();
                Array.Sort(chars);
                string sortedStr = new string(chars);

                // Increment count of this sorted pattern
                if (freqMap.ContainsKey(sortedStr)) {
                    freqMap[sortedStr]++;
                } else {
                    freqMap[sortedStr] = 1;
                }
            }
        }

        // Count total anagrammatic pairs from frequencies
        foreach (var entry in freqMap) {
            int f = entry.Value;

            // Choose any 2 from f => f * (f - 1) / 2
            if (f > 1) {
                count += (f * (f - 1)) / 2;
            }
        }

        return count;
    }

    public static void Main() {

        string s = "xyyx";

        Console.WriteLine(countAnagramPairs(s));
    }
}
JavaScript
function countAnagramPairs(s) {

    let n = s.length;
    let count = 0;

    // Map to store frequency of sorted substrings
    let freqMap = new Map();

    // Generate all substrings
    for (let i = 0; i < n; i++) {
        let curr = "";

        for (let j = i; j < n; j++) {
            curr += s[j];

            // Sort characters of the current substring
            let sortedStr = curr.split('').sort().join('');

            // Increment count of this sorted pattern
            if (freqMap.has(sortedStr)) {
                freqMap.set(sortedStr, freqMap.get(sortedStr) + 1);
            } else {
                freqMap.set(sortedStr, 1);
            }
        }
    }

    // Count total anagrammatic pairs from frequencies
    for (let f of freqMap.values()) {

        // Choose any 2 from f => f * (f - 1) / 2
        if (f > 1) {
            count += (f * (f - 1)) / 2;
        }
    }

    return count;
}

//Driver Code
let s = "xyyx";

console.log(countAnagramPairs(s));

Output
4

[Expected Approach 2] Using Hash Map - O(n^2) Time and O(n^2) Space

Fix a starting index and expand the substring one character at a time while maintaining a frequency array of size 26. Use this frequency array as a signature (hash key) in a map to count how many times the same pattern has appeared. If a pattern repeats, add its previous frequency to the answer since those substrings form anagram pairs.

C++
#include <iostream>
#include <unordered_map>
using namespace std;

int countAnagramPairs(string s) {
    int n = s.length();
    int count = 0;

    unordered_map<string, int> mp;

    for (int i = 0; i < n; i++) {

        vector<int> freq(26, 0);

        for (int j = i; j < n; j++) {

            freq[s[j] - 'a']++;

            string key = "";
            for (int k = 0; k < 26; k++) {
                key += to_string(freq[k]) + "#";
            }

            count += mp[key];
            mp[key]++;
        }
    }

    return count;
}

int main() {
    string s = "abba";
    cout << countAnagramPairs(s);
    return 0;
}
Java
import java.util.*;

public class GFG {

    static int countAnagramPairs(String s) {
        int n = s.length();
        int count = 0;

        HashMap<String, Integer> mp = new HashMap<>();

        for (int i = 0; i < n; i++) {

            int[] freq = new int[26];

            for (int j = i; j < n; j++) {

                freq[s.charAt(j) - 'a']++;

                String key = "";
                for (int k = 0; k < 26; k++) {
                    key += freq[k] + "#";
                }

                count += mp.getOrDefault(key, 0);
                mp.put(key, mp.getOrDefault(key, 0) + 1);
            }
        }

        return count;
    }

    public static void main(String[] args) {
        String s = "abba";
        System.out.println(countAnagramPairs(s));
    }
}
Python
def countAnagramPairs(s):
    n = len(s)
    count = 0
    mp = {}

    for i in range(n):
        freq = [0] * 26

        for j in range(i, n):
            freq[ord(s[j]) - ord('a')] += 1

            key = tuple(freq)  

            count += mp.get(key, 0)
            mp[key] = mp.get(key, 0) + 1

    return count

s = "abba"
print(countAnagramPairs(s))
C#
using System;
using System.Collections.Generic;

public class GFG
{
    static int countAnagramPairs(string s)
    {
        int n = s.Length;
        int count = 0;

        Dictionary<string, int> map = new Dictionary<string, int>();

        for (int i = 0; i < n; i++)
        {
            int[] freq = new int[26];

            for (int j = i; j < n; j++)
            {
                freq[s[j] - 'a']++;

                string key = string.Join(",", freq);

                if (map.ContainsKey(key))
                {
                    count += map[key];
                    map[key]++;
                }
                else
                {
                    map[key] = 1;
                }
            }
        }

        return count;
    }

    public static void Main()
    {
        string s = "abba";
        Console.WriteLine(countAnagramPairs(s));  
    }
}
JavaScript
function countAnagramPairs(s) {
    let n = s.length;
    let count = 0;
    let map = new Map();

    for (let i = 0; i < n; i++) {

        let freq = new Array(26).fill(0);

        for (let j = i; j < n; j++) {

            freq[s.charCodeAt(j) - 97]++;

            let key = freq.join(",");

            if (map.has(key)) {
                count += map.get(key);
                map.set(key, map.get(key) + 1);
            } else {
                map.set(key, 1);
            }
        }
    }

    return count;
}

let s = "abba";
console.log(countAnagramPairs(s));

Output
4
Comment