考えられるハッシュ関数の 1 つは、(英単語のみを想定して) 各文字の出現回数のソートされたカウントです。したがって、「アナグラム」の場合、[('a', 3), ('g', 1), ('n', 1), ('m', 1), ('r',1)] を生成します。
または、単語からビットマスクを生成することで、不正確なグループ化を取得できます。ビット 0 ~ 25 の各ビットは、その文字の有無を表します (ビット 0 は「a」を表し、ビット 25 は「z」を表します)。ただし、ハッシュされた各グループをさらに分割して、「to」と「to」などを区別するために、もう少し処理を行う必要があります。
これらのアイデアは役に立ちますか? 特定の実装言語を念頭に置いていますか (C++、Python、または Scala を実行できます)。
編集:Scalaコードと出力の例をいくつか追加しました:
OK: 私は現在 Scala モードにいるので、あなたが求めていることを実行するために何かをノックアップしましたが、(エヘム) Scala や関数型プログラミングに精通していない場合は、あまり明確ではないかもしれません.
ここから英単語の大きなリストを使用します: http://scrapmaker.com/data/wordlists/twelve-dicts/2of12.txt
この Scala コードを実行します (スクリプト モードで Scala 2.9 を使用すると、約 40,000 語の辞書をコンパイルする時間を含めて約 5 秒かかります。最も効率的なコードではありませんが、最初に頭に浮かんだことです)。
// 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(_<_)