Учитывая массив строк, вернуть все группы строк, которые являются анаграммами

Учитывая массив строк, вернуть все группы строк, которые являются анаграммами.

Мои решения:

Для каждого строкового слова в массиве отсортируйте его O(m lg m), m — средняя длина слова.

Создайте хеш-таблицу ‹ строка, список >.

Поместите отсортированное слово в хэш-таблицу в качестве ключа, а также сгенерируйте все перестановки (O (m!)) слова, ищите каждую перестановку в словаре (карте дерева префиксов) с O (m), если она есть в словаре , поместите (O(1)) его в хеш-таблицу так, чтобы все переставленные слова попали в список с одним и тем же ключом.

Итого, O(n * m * lg m * m!) времени и O(n* m!) пространства, n - размер данного массива.

Если m очень велико, это неэффективно, m! .

Любые лучшие решения?

Благодарность


person user1002288    schedule 16.12.2011    source источник


Ответы (5)


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

Это дало бы нам следующее отображение: { a => 2, b => 3, c => 5, d => 7 и т. д.}

Теперь подсчитайте буквы в слове, которое вы хотите представить как целое число, и постройте целое число следующим образом:

Псевдокод:

result = 1
for each letter:
....result *= power(prime[letter], count(letter,word)

Некоторые примеры:

аааа => 2^4

aabb => 2^2 * 3^2 = bbaa = baba = ...

и так далее.

Таким образом, у вас будет целое число, представляющее каждое слово в вашем словаре, и слово, которое вы хотите проверить, можно будет преобразовать в целое число. Таким образом, если n — это размер вашего списка слов, а k — это размер самого длинного слова, потребуется O(nk) для создания нового словаря и O(k) для проверки нового слова.

У Hackthissite.com есть задача программирования, которая заключается в следующем: если у вас есть зашифрованное слово, посмотрите его в словаре, чтобы увидеть, есть ли какие-либо анаграммы для него в словаре. Существует хорошая статья об эффективном решении проблемы, из которой я позаимствовал ответ, она также входит в подробнее о дальнейшей оптимизации.

person silleknarf    schedule 16.12.2011
comment
Мы также должны учитывать стоимость построения алфавита O(sizeof(dictionary) * k). В вашем решении O (nk) предназначен для данного массива строк, а не для словаря. Благодарность - person user1002288; 17.12.2011
comment
Да, я должен был быть более ясным, n - это размер словаря, и массив строк, который вам дан, будет, возможно, l, а затем время выполнения будет O (lk) после того, как словарь будет построен - person silleknarf; 17.12.2011
comment
Это сумасшедшее решение. Используя вашу схему, слово «пицца» дает значение, превышающее 9,6 e19. Ваши значения будут регулярно превышать диапазон 64-битных чисел, и есть английские слова, которые будут превышать диапазон 128-битных чисел. Вам лучше использовать строковые ключи. - person Jim Mischel; 20.02.2018

используйте сортировку подсчетом, чтобы отсортировать слово, чтобы сортировку можно было выполнить за O (m). после сортировки сгенерировать ключ из слова и вставить узел (ключ, значение) в хеш-таблицу. Генерация ключа может быть достигнута за O(m).

Вы можете взять значение в (ключ, значение) как некоторый динамический массив, который может содержать более одной строки. Каждый раз, когда вы вставляете уже существующий ключ, просто вставляйте исходное слово, из которого сгенерирован ключ, в массив значений.

Таким образом, общая временная сложность O (mn), где n - общее количество слов (размер ввода).

Также по этой ссылке есть решение подобных проблем-> http://yourbitsandbytes.com/viewtopic.php?f=10&t=42

person Ameliorator    schedule 16.12.2011

#include <map>
#include <iostream>
#include <set>
#include <algorithm>

int main () {
  std::string word;
  std::map<std::string, std::set<std::string>> anagrams;
  while(std::cin >> word) {
    std::string sortedWord(word);
    std::sort(sortedWord.begin(), sortedWord.end());
    anagrams[sortedWord].insert(word);
  }
  for(auto& pair : anagrams) {
    for(auto& word : pair.second) {
      std::cout << word << " ";
    }
    std::cout << "\n";
  }
}

Я позволю тому, кто лучше меня разбирается в большом O-анализе, разобраться со сложностями.

person Robᵩ    schedule 16.12.2011
comment
m - максимальное количество символов в любой строке, n - общее количество строк. m * log m для сортировки каждой строки. m * log n для вставки в anagrams. m, так как каждое сравнение строк занимает O(m) времени. Следовательно, O(n * m * (log n + log m)) является верхней границей. - person viswanathgs; 17.12.2011

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

person Paddy3118    schedule 16.12.2011

Я не верю, что вы можете добиться большего успеха в терминах O, чем

  • сортировка букв каждого слова
  • сортировка списка отсортированных слов
  • каждый набор анаграмм теперь будет сгруппирован последовательно.
person Rafe    schedule 16.12.2011