The best way to group anagrams is by matching strings with some kind of histogram representation.
FUNCTION histogram [input] -> [output] "dog" -> (1xd, 1xg, 1xo) "god" -> (1xd, 1xg, 1xo) "foo" -> (1xf, 2xo)
Basically, with a linear scan of a string, you can create a histogram view of how much of each letter it contains. The small, finite alphabet makes it even easier (for example, with AZ , you only have an array of 26 numbers, one for each letter).
Now, anagrams are just words that have the same histogram.
Then you can have a multi-map data structure that maps the histogram to a list of words that have this histogram.
MULTIMAP [key] => [set of values] (1xd, 1xg, 1xo) => { "dog", "god" } (1xf, 2xo) => { "foo" }
Canonical trick form
Instead of working with histograms, you can also work on the "canonical form" of strings. Basically, you determine for each line what its canonical form is, and two words are anagrams if they have the same canonical form.
One convenient canonical form is to have letters in a string in sorted order.
FUNCTION canonize [input] -> [output] "dog" -> "dgo" "god" -> "dgo" "abracadabra" -> "aaaaabbcdrr"
Note that this is just one step after approaching the histogram: you essentially do a sort count to sort the letters.
This is the most practical solution in a programming language for your problem.
Complexity
The product of the histogram / canonical form of the word is practically O(1) (final alphabet size, final maximum word length).
With a good implementation of the hash get and put in the multimagel O(1) .
You can even have multiple multi-shots, one for each word length.
If there are words N , therefore all words in multimars, therefore, O(N) ; then the output of each group of anagrams simply resets the values ββin the multi-mars. This can also be done in O(N) .
This is certainly better than checking if each pair of words is anagram ( O(N^2) algorithm).