Разбивая и переставляя строку во все возможные комбинации - PullRequest
3 голосов
/ 08 июля 2011

Я хочу разбить и переставить строку во все возможные комбинации

Скажем, у меня есть строка: ABCDEF

Я хочу разбить ее и вывести все возможные комбинации

комбинация (6,6) = 1

ABCDEF

комбинация (6,5) = 6

BCDEF
ACDEF
ABDEF
ABCEF
ABCDF
ABCDE

комбинация (6,4) = 15

BCDE
ACDE
ABDE
ABCE
....
....
....
etc.

Комбинация (6,3) = 20

BCD
ACD
...
etc.

Комбинация (6,2) = 15 г. до н.э. и т. Д.

Однако выход также должен быть расположен в алфавитном порядке.

Как я это сделаю?

Спасибо!Любая помощь будет оценена!

Ответы [ 4 ]

4 голосов
/ 08 июля 2011

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

Обновление: как я думаю об этомБолее того, Fascicle 2 (Generation Permutations) на самом деле более полезен.Вы можете загрузить его бесплатно с http://www -cs-faculty.stanford.edu / ~ knuth /asc2b.ps.gz , хотя для его чтения вам понадобится gunzip и программа предварительного просмотра PostScript.Генерация подмножеств строки «ABCDE» является простой частью.Преобразуйте его в массив {'A', 'B', 'C', 'D', 'E'}, запустите цикл for от 0 до 2 ^ N-1, где N - длина массива, и обработайте каждое значениекак битовая маска элементов, которые вы храните.Таким образом, 00001, 00010, 00011, ... дает вам "A", "B", "AB", ...

Трудная часть генерирует все перестановки каждого подмножества, поэтому вы получаете "ABC"," BAC "," CAB "и т. Д. Алгоритм грубой силы (как в одном из других ответов) будет работать, но будет очень медленным, если строка длинная.У Кнута есть несколько быстрых алгоритмов, некоторые из которых будут генерировать перестановки в алфавитном порядке, если исходная строка была отсортирована в первую очередь.

2 голосов
/ 08 июля 2011

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

То есть test = e:1,s:1,t:2

Тогда, если кто-то ищет мир tset, он будет генерировать тот же хэш (e: 1, s: 1, t: 2), и bam у вас есть совпадение.

Я только что выполнил список слов (около 20 миллионов слов), сгенерировалхэш для каждого из них, и положить его в таблицу MySQL, я могу найти все перестановки слова (которые все еще сами слова, ака ered вернет deer и reed) в считанные секунды.

1 голос
/ 08 июля 2011

Вы можете сгенерировать каждую перестановку, увеличив счетчик и преобразовав значение счетчика в основание n, где n - количество букв в вашем входе.Откажитесь от любых значений, содержащих повторяющиеся буквы, и то, что вы оставили, это возможные слова скрэббл в алфавитном порядке, при условии, что ваш массив был отсортирован.

Вам нужно будет сосчитать до (n ^ (n-1)) * (n+1) чтобы получить е * п!возможные слова скрэббл.

char[] Letters = new char[] { 'A', 'B', 'C', 'D', 'E', 'F' };

// calculate e*n! (int)Math.Floor(Math.E * Math.Factorial(Letters.Length))
int x = 0;
for (int i = 1; i <= Letters.Length; i++)
    x = (x + 1) * i;

for (int i = 1; x > 0; i++)
{
    string Word = BaseX(i, Letters.Length, Letters);
    if (NoRepeat(Word))
    {
        Console.WriteLine(Word);
        x--;
    }
}

BaseX возвращает строковое представление значения для данной базы и указанных символов:

string BaseX(int Value, int Base, char[] Symbols)
{
    StringBuilder s = new StringBuilder();

    while (Value > Base)
    {
        s.Insert(0, Symbols[Value % Base]);
        Value /= Base;
    }

    s.Insert(0, Symbols[Value - 1]);
    return s.ToString();
}

NoRepeat возвращает false, если любая буква встречается более одного раза:

bool NoRepeat(string s)
{
    bool[] Test = new bool[256];

    foreach (char c in s)
        if (Test[(byte)c])
            return false;
        else
            Test[(byte)c] = true;

    return true;
}
0 голосов
/ 08 июля 2011
  1. Сортировка строки в алфавитном порядке.Скажите ABCDEF (ваш пример)
  2. Подготовьте карту между индексом и символом

map [0] = 'A';карта [1] = 'B';... карта [5] = 'F'

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

Комбинация (6,3):

for (int i = 0; i < 6 - 2; i++)
    for (int j = i + 1; j < 6 - 1; j++)
        for (int k = j + 1; k < 6; k++)
        {
            string strComb = map[i] + map[j] + map[k];
        }

Это в основномидея, вы могли бы улучшить по-своему.

Свяжитесь со мной, если вы хотите более подробно!

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