Все анаграммы в файле

Источник : Microsoft Интервью Вопрос

нам предоставляется файл, содержащий слова.Нам нужно определить все анаграммы, присутствующие в нем .

может кто-то предложить наиболее оптимальный алгоритм для этого.

единственный способ я знаю сортировка всех слов, затем проверка .

4 ответов


хорошо бы знать больше о данных прежде чем предлагать алгоритм, но давайте просто предположим, что слова в английском языке в одном случае.

давайте назначим каждой букве простое число от 2 до 101. Для каждого слова мы можем подсчитать его "число анаграммы", умножив его буквы соответствующими числами.

объявим словарь пар {number, list}. И один список для сбора анаграмм.

тогда мы можем собрать анаграммы в два шаги: просто пройдите через файл и поместите каждое слово в список словаря в соответствии с его "номером анаграммы"; пройдите по карте и для каждого списка пар длиной более 1 сохраните его содержимое в одном большом списке анаграмм.

обновление:

import operator

words = ["thore", "ganamar", "notanagram", "anagram", "other"]

letter_code = {'a':2, 'b':3, 'c':5, 'd':7, 'e':11, 'f':13, 'g':17, 'h':19, 'i':23, 'j':29, 'k':31, 'l':37, 'm':41, 'n':43, 
            'o':47, 'p':53, 'q':59, 'r':61, 's':67, 't':71, 'u':73, 'v':79, 'w':83, 'x':89, 'y':97, 'z':101}

def evaluate(word):
    return reduce( operator.mul, [letter_code[letter] for letter in word] )

anagram_map = {}
anagram_list = []
for word in words:
    anagram_number = evaluate(word)
    if anagram_number in anagram_map:
        anagram_map[ anagram_number ] += [word]
    else:
        anagram_map[ anagram_number ] = [word]

    if len(anagram_map[ anagram_number ]) == 2:
        anagram_list += anagram_map[ anagram_number ] 
    elif len(anagram_map[ anagram_number ]) > 2:
        anagram_list += [ word ]

print anagram_list

конечно реализация может быть оптимизирована дальше. Например, вам действительно не нужна карта анаграмм, просто счетчики будут в порядке. Но я думаю, что код лучше всего иллюстрирует эту идею.


вы можете использовать "Триэс".Trie (производное от извлечения) - это дерево поиска несколькими способами. Пытается использовать алгоритмы сопоставления шаблонов. Основное использование-создание программ проверки орфографии, но я думаю, что это может помочь вашему делу.. Посмотрите на эту ссылку http://ww0.java4.datastructures.net/handouts/Tries.pdf


Я просто сделал это не так давно, по-другому.

  1. разделить содержимое файла на массив слов
  2. создайте HashMap, который сопоставляет строку ключа со связанным списком строк
  3. для каждого слова в массиве отсортируйте Буквы в слове и используйте это как ключ к связанному списку анаграмм

public static void allAnagrams2 (строка s) { String[] input = s.toLowerCase ().replaceAll ("[^a-z^\s]", "").сплит("\с"); HashMap> hm = новый HashMap>();

    for (int i = 0; i < input.length; i++) {
        String current = input[i];

        char[] chars = current.toCharArray();
        Arrays.sort(chars);
        String key = new String(chars);

        LinkedList<String> ll = hm.containsKey(key) ? hm.get(key) : new LinkedList<String>();
        ll.add(current);

        if (!hm.containsKey(key))
            hm.put(key, ll);
    }
}

немного отличается от подхода, описанного выше. Вместо этого возвращаем хеш-карту анаграмм.

Public static Hashmap<String> anagrams(String [] list){

    Hashmap<String, String> hm = new Hashmap<String, String>();
    Hashmap<String> anagrams = new Hashmap<String>();

    for (int i=0;i<list.length;i++){
        char[] chars = list[i].toCharArray();
        Arrays.sort(chars);
        String k = chars.toString();
        if(hm.containsKey(k)){
            anagrams.put(k);
            anagrams.put(hm.get(k));
        }else{
            hm.put(k, list[i]); 
        }
    }
}