Строки и возможные анаграммы этих строк

Я делаю небольшой проект (на Java), пока uni отсутствует, просто чтобы проверить себя, и я наткнулся на камень преткновения.

Я пытаюсь написать программу, которая будет считывать из текстовой версии словаря, сохранять ее в ds (структуре данных), а затем запрашивать у пользователя случайную строку (желательно бессмысленную строку, но только буквы и -'s , ни цифр, ни других знаков препинания — меня больше ничего не интересует), узнать все анаграммы введенной строки, сравнить ее со словарем ds и вернуть список всех возможных анаграмм, которые есть в словаре.

Хорошо, для шагов 1 и 2 (чтение из словаря), когда я читаю все, я сохраняю это на карте, где ключи — это буквы алфавита, а значения — это ArrayLists, в которых хранятся все слова, начинающиеся с этой буквы. .

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

Лучше разбить его на char и поиграть с ним таким образом, или разделить его и сохранить как строковые элементы? Я видел пример кода в Интернете на разных сайтах, но я не хочу видеть код, я хотел бы знать, какой подход / идеи лежат в основе разработки решения для этого, поскольку я как бы застрял, как даже начать :(

Я имею в виду, я думаю, что знаю, как я буду сравнивать со словарем ds после того, как я сгенерирую все перестановки.

Будут полезны любые советы, но не код, если можно, а просто идеи.

P.S. Если вы хотите увидеть мой код до сих пор (по какой-либо причине), я опубликую то, что у меня есть.


person andrewktmeikle    schedule 08.06.2011    source источник
comment
По сути, вы пишете решатель анаграмм. scrabblecheat.com   -  person jjnguy    schedule 08.06.2011
comment
Я знаю, что лучший способ - использовать какую-то древовидную структуру. Но я не уверен на 100%, как это сделать.   -  person jjnguy    schedule 08.06.2011
comment
@Джефф Фостер, да, если подумать, я имею в виду анаграммы! Черт, я даже не мог подумать об этом слове: / нужно сделать репост этого сейчас. Спасибо! действительно дерево, чтобы решить эту проблему? Как так?   -  person andrewktmeikle    schedule 08.06.2011
comment
Это называется словарь. Мне пришлось написать его для летнего курса в CMU, очень простая программа. Ваша поддерживающая структура данных — действительно важная часть.   -  person if_zero_equals_one    schedule 08.06.2011
comment
ха! На самом деле я до последнего не понимал, что на самом деле ты хотел сказать слово «три»: P думал, что ты хотел сказать «дерево», но ошибся в написании: P, спасибо: D   -  person andrewktmeikle    schedule 08.06.2011


Ответы (3)


Было бы полезно, если бы вы привели пример, поясняющий проблему. Насколько я понимаю, вы говорите, что если пользователь введет, скажем, «islent», программа ответит «listen», «silent» и «enlist».

Я думаю, что самым простым решением было бы взять каждое слово из вашего словаря и сохранить его как со словом в том виде, в котором оно было введено, так и со словом, в котором буквы переставлены в алфавитном порядке. Назовем это «каноническим значением». Индекс канонического значения. Затем преобразуйте ввод в каноническое значение и выполните прямой поиск совпадений.

Продолжая приведенный выше пример, когда мы создаем словарь и видим слово «слушаем», мы переводим его на «eilnst» и сохраняем «eilnst -> listen». Мы также сохранили бы «eilnst -> тихий» и «eilnst -> enlist». Затем мы получаем входную строку, преобразуем ее в «eilnst», выполняем поиск и сразу же находим три совпадения.

person Jay    schedule 08.06.2011
comment
Почти так же, как у вас, например, если бы у меня было переполнение, я бы использовал все слова в английском словаре, чем можно сделать из строки длиной 8 (например, той же длины, что и искомое слово). Например, я получаю ckod, я мог бы дать док как один из выходов, но kodc не будет выходом, так как его нет в словаре - person andrewktmeikle; 08.06.2011
comment
Большое спасибо! Есть несколько вещей, которые я собираюсь попробовать сейчас, очень ценю советы, очень полезные! - person andrewktmeikle; 08.06.2011

public String str = "overflow";
public ArrayList<String> possibilities = new ArrayList<String>();
public void main(String[] args)
{
    permu(new boolean[str.length()],"");
}
public void permu(boolean[] used, String cur)
{
    if (cur.length()==str.length())
    {
        possibilities.add(cur);
        return;
    }
    for (int a = 0; a < str.length(); a++)
    {
        if (!used[a])
        {
            used[a]=true;
            cur+=str.charAt(a);
            permu(used,cur);
            used[a] = false;
            cur = cur.substring(0,cur.length()-1);
        }
    }
}

Простой с действительно ужасным временем выполнения, но он выполнит свою работу.

РЕДАКТИРОВАНИЕ: более продвинутая версия называется Dictionary Trie. По сути, это дерево, в котором каждый узел имеет 26 узлов, по одному на каждую букву алфавита. И каждый узел также имеет логическое значение, указывающее, является ли это концом слова. Благодаря этому вы можете легко вставлять слова в словарь и легко проверять, находитесь ли вы на правильном пути для создания слова.

Я вставлю код, если хотите

person if_zero_equals_one    schedule 08.06.2011
comment
Гораздо лучшим применением этого является Dictionary trie, в котором вы берете каждый символ и перебираете trie, чтобы увидеть, существует ли префикс, прежде чем продолжить этот путь. - person if_zero_equals_one; 08.06.2011
comment
Спасибо чувак! просто ищу некоторые идеи, хотя и не реальный код, но все равно спасибо за усилия! - person andrewktmeikle; 08.06.2011
comment
+1 за идею дерева (на самом деле я думал об этом). Поместите это как заметку внутри вашего поста! - person helios; 08.06.2011
comment
Нет, все в порядке, вставка кода не требуется, я проведу исследование самостоятельно, спасибо: D, я уберу это и тоже поработаю над этим! Очень признателен за очень полезный вклад! :D еще раз спасибо! - person andrewktmeikle; 08.06.2011

Вычисление перестановок действительно кажется плохой идеей в этом случае. Слово «переполнение», например, имеет 40320 перестановок.

Лучший способ узнать, является ли одно слово перестановкой другого, — это подсчитать, сколько раз встречается каждая буква (это будет кортеж из 26), и сравнить эти кортежи друг с другом.

person aioobe    schedule 08.06.2011
comment
Ах, ладно, плохо, я не имею в виду ВСЕ перестановки (должен был прояснить это), меня интересуют только все перестановки строки одинаковой длины, например, все слова, которые можно составить из переполнения, которые есть в словаре и имеют ту же длину, что и переполнение - person andrewktmeikle; 08.06.2011
comment
Что ты имеешь в виду? Очевидно, что все перестановки имеют одинаковую длину. - person aioobe; 08.06.2011
comment
Просто хотел прояснить, я не хочу, чтобы слова были меньше исходного слова. Хорошо, поищите в словаре слова, которые включают все буквы из строки поиска? - person andrewktmeikle; 08.06.2011
comment
Точно. Вычисление всех перестановок входной строки, скорее всего, будет невозможным. - person aioobe; 08.06.2011
comment
Спасибо, хороший совет, но не будет ли дольше просматривать 273000 слов для всех слов, которые его содержат, чем генерировать 40320 анаграмм и бинарный поиск по соответствующей букве, чтобы проверить, есть ли в ней? Я мог бы, конечно, установить правила, чтобы отбрасывать определенные анаграммы, основанные на правилах английского языка, но просматривать словарь в поисках (в произвольном порядке) слов, содержащих все буквы, было бы хуже, не так ли? - person andrewktmeikle; 08.06.2011
comment
Я предлагаю вам создать карту из 26-кортежа в набор слов, соответствующих этому профилю. (Предполагая, что у вас есть n слов, каждое из которых имеет максимальную длину m, это займет O(nm).) Когда пользователь вводит слово, вы вычисляете профиль для этого слова и ищете анаграммы на карте. - person aioobe; 08.06.2011
comment
Да, это план. Что возвращает меня к OP, как я на самом деле делаю перестановку для создания анаграмм? - person andrewktmeikle; 08.06.2011
comment
Вы ничего не переделываете! Вы создаете список из 26 целых чисел. Прокрутите символы в слове. Если вы сталкиваетесь с a, вы увеличиваете целое число с индексом 0, если вы сталкиваетесь с b, вы увеличиваете целое число с индексом 1 и так далее. - person aioobe; 08.06.2011
comment
Оооо! Очень приятно! Теперь у меня есть пара вещей, чтобы попробовать! Очень ценный вклад от очень активного и полезного сообщества! - person andrewktmeikle; 08.06.2011