Одной из возможных хэш-функций может быть (предполагая только английские слова) отсортированный подсчет количества вхождений каждой буквы. Таким образом, для «анаграммы» вы должны сгенерировать [('a', 3), ('g', 1), ('n', 1), ('m', 1), ('r', 1)].
В качестве альтернативы вы можете получить неточную группировку, сгенерировав битовую маску из вашего слова, где для битов 0-25 каждый бит представляет наличие или отсутствие этой буквы (от бита 0, представляющего «а», до бита 25, представляющего «z»). Но тогда вам придется выполнить немного больше обработки, чтобы разделить каждую хешированную группу, чтобы различать, например. «к» от «тоже».
Любая из этих идей помогает? Какой-то конкретный язык реализации (я мог бы сделать C++, python или Scala)?
Редактировать: добавлен пример кода Scala и вывод:
ОК: В данный момент я нахожусь в режиме Scala, поэтому я кое-что придумал, чтобы сделать то, что вы просите, но (кхм) это может быть не очень понятно, если вы не знакомы со Scala или функциональным программированием.
Используя большой список английских слов отсюда: http://scrapmaker.com/data/wordlists/twelve-dicts/2of12.txt
Я запускаю на них этот код Scala (занимает около 5 секунд, используя Scala 2.9 в режиме скрипта, включая время на компиляцию, со словарем около 40 000 слов. Не самый эффективный код, но первое, что пришло в голову).
// Hashing function to go from a word to a sorted list of letter counts
def toHash(b:String) = b.groupBy(x=>x).map(v => (v._1, v._2.size) ).toList.sortWith(_._1 < _._1)
// Read all words from file, one word per line
val lines = scala.io.Source.fromFile("2of12.txt").getLines
// Go from list of words to list of (hashed word, word)
val hashed = lines.map( l => (toHash(l), l) ).toList
// Group all the words by hash (hence group all anagrams together)
val grouped = hashed.groupBy( x => x._1 ).map( els => (els._1, els._2.map(_._2)) )
// Sort the resultant anagram sets so the largest come first
val sorted = grouped.toList.sortWith( _._2.size > _._2.size )
for ( set <- sorted.slice(0, 10) )
{
println( set._2 )
}
Это выводит первые 10 наборов анаграмм (сначала наборы с наибольшим количеством членов):
List(caret, cater, crate, react, trace)
List(reins, resin, rinse, risen, siren)
List(luster, result, rustle, sutler, ulster)
List(astir, sitar, stair, stria, tarsi)
List(latrine, ratline, reliant, retinal)
List(caper, crape, pacer, recap)
List(merit, miter, remit, timer)
List(notes, onset, steno, stone)
List(lair, liar, lira, rail)
List(drawer, redraw, reward, warder)
Обратите внимание, что здесь используется первое предложение (список количества букв), а не более сложный метод битовой маски.
Редактирование 2. Вы можете заменить хеш-функцию простой сортировкой символов каждого слова (как предлагает JAB) и получить тот же результат с более четким/быстрым кодом:
def toHash(b:String) = b.toList.sortWith(_<_)
person
Alex Wilson
schedule
19.06.2012