Count Anagrams
HardUpdated: Aug 2, 2025
Practice on:
Problem
You are given a string s containing one or more words. Every consecutive pair of words is separated by a single space ' '.
A string t is an anagram of string s if the ith word of t is a
permutation of the ith word of s.
- For example,
"acb dfe"is an anagram of"abc def", but"def cab"and"adc bef"are not.
Return _the number ofdistinct anagrams of _s. Since the answer may be very large, return it modulo 10^9 + 7.
Examples
Example 1
Input: s = "too hot"
Output: 18
Explanation: Some of the anagrams of the given string are "too hot", "oot hot", "oto toh", "too toh", and "too oht".
Example 2
Input: s = "aa"
Output: 1
Explanation: There is only one anagram possible for the given string.
Constraints
1 <= s.length <= 10^5sconsists of lowercase English letters and spaces' '.- There is single space between consecutive words.
Solution
Method 1 – Combinatorics with Modular Inverse 1
Intuition
Each word in the string can be rearranged independently. The number of anagrams for a word is the multinomial coefficient: total letters factorial divided by the product of factorials of each letter's frequency. The answer is the product of anagram counts for all words, modulo 10^9+7.
Approach
- Split the string into words by spaces.
- For each word:
- Count the frequency of each character.
- Compute the total number of anagrams as total_letters! / (freq1! * freq2! * ...).
- Use modular arithmetic and precomputed factorials/inverses for efficiency.
- Multiply the results for all words, taking modulo 10^9+7.
- Return the result.
Code
C++
class Solution {
public:
int countAnagrams(string s) {
const int MOD = 1e9+7, N = 100005;
vector<long long> fact(N), inv(N);
fact[0] = 1;
for (int i = 1; i < N; ++i) fact[i] = fact[i-1] * i % MOD;
inv[N-1] = powmod(fact[N-1], MOD-2, MOD);
for (int i = N-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % MOD;
auto split = [](string& s) {
vector<string> res;
string t;
for (char c : s) {
if (c == ' ') {
if (!t.empty()) res.push_back(t);
t.clear();
} else t += c;
}
if (!t.empty()) res.push_back(t);
return res;
};
auto words = split(s);
long long ans = 1;
for (auto& w : words) {
vector<int> cnt(26);
for (char c : w) cnt[c-'a']++;
long long cur = fact[w.size()];
for (int x : cnt) cur = cur * inv[x] % MOD;
ans = ans * cur % MOD;
}
return ans;
}
long long powmod(long long a, long long b, long long m) {
long long res = 1;
while (b) {
if (b & 1) res = res * a % m;
a = a * a % m;
b >>= 1;
}
return res;
}
};
Go
func countAnagrams(s string) int {
const MOD = 1_000_000_007
N := 100005
fact := make([]int, N)
inv := make([]int, N)
fact[0] = 1
for i := 1; i < N; i++ {
fact[i] = fact[i-1] * i % MOD
}
inv[N-1] = powmod(fact[N-1], MOD-2, MOD)
for i := N-2; i >= 0; i-- {
inv[i] = inv[i+1] * (i+1) % MOD
}
words := strings.Fields(s)
ans := 1
for _, w := range words {
cnt := [26]int{}
for _, c := range w {
cnt[c-'a']++
}
cur := fact[len(w)]
for _, x := range cnt {
cur = cur * inv[x] % MOD
}
ans = ans * cur % MOD
}
return ans
}
func powmod(a, b, m int) int {
res := 1
for b > 0 {
if b&1 == 1 {
res = res * a % m
}
a = a * a % m
b >>= 1
}
return res
}
Java
class Solution {
public int countAnagrams(String s) {
final int MOD = 1_000_000_007, N = 100005;
long[] fact = new long[N], inv = new long[N];
fact[0] = 1;
for (int i = 1; i < N; ++i) fact[i] = fact[i-1] * i % MOD;
inv[N-1] = powmod(fact[N-1], MOD-2, MOD);
for (int i = N-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % MOD;
String[] words = s.split(" ");
long ans = 1;
for (String w : words) {
int[] cnt = new int[26];
for (char c : w.toCharArray()) cnt[c-'a']++;
long cur = fact[w.length()];
for (int x : cnt) cur = cur * inv[x] % MOD;
ans = ans * cur % MOD;
}
return (int)ans;
}
long powmod(long a, long b, long m) {
long res = 1;
while (b > 0) {
if ((b & 1) == 1) res = res * a % m;
a = a * a % m;
b >>= 1;
}
return res;
}
}
Kotlin
class Solution {
fun countAnagrams(s: String): Int {
val MOD = 1_000_000_007
val N = 100005
val fact = LongArray(N)
val inv = LongArray(N)
fact[0] = 1L
for (i in 1 until N) fact[i] = fact[i-1] * i % MOD
inv[N-1] = powmod(fact[N-1], (MOD-2).toLong(), MOD.toLong())
for (i in N-2 downTo 0) inv[i] = inv[i+1] * (i+1) % MOD
val words = s.split(" ")
var ans = 1L
for (w in words) {
val cnt = IntArray(26)
for (c in w) cnt[c-'a']++
var cur = fact[w.length]
for (x in cnt) cur = cur * inv[x] % MOD
ans = ans * cur % MOD
}
return ans.toInt()
}
fun powmod(a: Long, b: Long, m: Long): Long {
var a = a; var b = b; var res = 1L
while (b > 0) {
if (b and 1L == 1L) res = res * a % m
a = a * a % m
b = b shr 1
}
return res
}
}
Python
class Solution:
def countAnagrams(self, s: str) -> int:
MOD = 10**9 + 7
N = 100005
fact = [1] * N
inv = [1] * N
for i in range(1, N):
fact[i] = fact[i-1] * i % MOD
inv[N-1] = pow(fact[N-1], MOD-2, MOD)
for i in range(N-2, -1, -1):
inv[i] = inv[i+1] * (i+1) % MOD
ans = 1
for w in s.split():
cnt = [0] * 26
for c in w:
cnt[ord(c)-ord('a')] += 1
cur = fact[len(w)]
for x in cnt:
cur = cur * inv[x] % MOD
ans = ans * cur % MOD
return ans
Rust
impl Solution {
pub fn count_anagrams(s: String) -> i32 {
const MOD: i64 = 1_000_000_007;
const N: usize = 100005;
let mut fact = vec![1i64; N];
let mut inv = vec![1i64; N];
for i in 1..N {
fact[i] = fact[i-1] * i as i64 % MOD;
}
inv[N-1] = powmod(fact[N-1], MOD-2, MOD);
for i in (0..N-1).rev() {
inv[i] = inv[i+1] * (i as i64 + 1) % MOD;
}
let words: Vec<&str> = s.split_whitespace().collect();
let mut ans = 1i64;
for w in words {
let mut cnt = [0; 26];
for c in w.chars() {
cnt[(c as u8 - b'a') as usize] += 1;
}
let mut cur = fact[w.len()];
for &x in &cnt {
cur = cur * inv[x] % MOD;
}
ans = ans * cur % MOD;
}
ans as i32
}
}
fn powmod(mut a: i64, mut b: i64, m: i64) -> i64 {
let mut res = 1;
while b > 0 {
if b & 1 == 1 {
res = res * a % m;
}
a = a * a % m;
b >>= 1;
}
res
}
TypeScript
class Solution {
countAnagrams(s: string): number {
const MOD = 1_000_000_007, N = 100005;
const fact: number[] = Array(N).fill(1), inv: number[] = Array(N).fill(1);
for (let i = 1; i < N; ++i) fact[i] = fact[i-1] * i % MOD;
inv[N-1] = powmod(fact[N-1], MOD-2, MOD);
for (let i = N-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % MOD;
let ans = 1;
for (const w of s.split(' ')) {
const cnt = Array(26).fill(0);
for (const c of w) cnt[c.charCodeAt(0)-97]++;
let cur = fact[w.length];
for (const x of cnt) cur = cur * inv[x] % MOD;
ans = ans * cur % MOD;
}
return ans;
}
}
function powmod(a: number, b: number, m: number): number {
let res = 1;
while (b > 0) {
if (b & 1) res = res * a % m;
a = a * a % m;
b >>= 1;
}
return res;
}
Complexity
- ⏰ Time complexity:
O(L + W * D), where L is the length of s, W is the number of words, and D is the max word length. Precomputation is O(N), and each word is processed in O(D). - 🧺 Space complexity:
O(N), for factorials and inverses.