Для написания решателя анаграмм, который вы связали, запрашиваемый вами алгоритм не нужен. Это также очень дорого.
Давайте посмотрим на 6-буквенное слово, например MONKEY
. Все 6 букв слова разные, поэтому вы должны создать:
- 6 * 5 * 4 * 3 * 2 * 1 различных 6-буквенных слов
- 6 * 5 * 4 * 3 * 2 разных пятибуквенных слова
- 6 * 5 * 4 * 3 разных 4-х буквенных слова
- 6 * 5 * 4 разных 3-х буквенных слова
- 6 * 5 разных двухбуквенных слов
- Всего 1950 слов
Теперь, по-видимому, вы не пытаетесь выплевывать все 1950 слов (например, «OEYKMN») в виде анаграмм (которые они есть, но большинство из них также являются бредом). Я предполагаю, что у вас есть словарь юридических английских слов, и вы просто хотите проверить, являются ли какие-либо из этих слов анаграммами слова запроса, с возможностью не использовать все буквы.
Если это так, то проблема проста.
Чтобы определить, являются ли 2 слова анаграммами друг друга, все, что вам нужно сделать, это подсчитать, сколько раз используются каждая буква, и сравнить эти числа!
Давайте ограничимся только 26 буквами A-Z без учета регистра. Вам нужно написать функцию countLetters
, которая берет слово и возвращает массив из 26 чисел. Первое число в массиве соответствует счету буквы A
в слове, второе число соответствует счету B
и т. Д.
Тогда два слова W1
и W2
являются точной анаграммой, если countLetters(W1)[i] == countLetters(W2)[i]
для каждого i
! То есть каждое слово использует каждую букву одинаковое количество раз!
Для того, что я бы назвал поданаграммами (MONEY
- это поданаграмма MONKEY
), W1
- это поданаграмма W2
, если countLetters(W1)[i] <= countLetters(W2)[i]
для каждого i
! То есть в поданаграмме может использоваться меньше определенных букв, но не больше!
(примечание: MONKEY
также является поданаграммой MONKEY
).
Это должно дать вам достаточно быстрый алгоритм, при котором для заданной строки запроса все, что вам нужно сделать, - это один раз прочитать словарь, сравнив массив букв каждого слова с массивом букв слова запроса. Вы можете сделать небольшую оптимизацию, но этого должно быть достаточно.
В качестве альтернативы, если вам нужна максимальная производительность, вы можете предварительно обработать словарь (который известен заранее) и создать ориентированный ациклический граф взаимосвязи поданаграмм.
Вот часть такого графика для иллюстрации:
D=1,G=1,O=1 ----------> D=1,O=1
{dog,god} \ {do,od}
\
\-------> G=1,O=1
{go}
По сути, каждый узел является корзиной для всех слов, имеющих одинаковый массив букв (т.е. они являются точными анаграммами). Тогда есть узел от N1
до N2
, если массив N2
равен <=
(как определено выше) N1
массив (вы можете выполнить переходное сокращение, чтобы сохранить наименьшее количество ребер).
Затем, чтобы составить список всех поданаграмм слова, все, что вам нужно сделать, это найти узел, соответствующий его массиву счетчиков букв, и рекурсивно исследовать все узлы, доступные из этого узла. Все их ведра содержат субанаграммы.