Сгенерировать все возможные совпадения регулярного выражения

Как я могу получить все возможные совпадения регулярного выражения

Например:

((a,b,c)o(m,v)p,b)

Строки, сгенерированные из приведенного выше выражения, будут такими:

аомп

бомба

комп

аовп

бовп

ковп

b


person Nilutpal Borgohain    schedule 04.03.2015    source источник
comment
Создайте DFA, принимающий язык регулярного выражения, выполните BFS и выводите только тогда, когда вы находитесь в принимающем состоянии. Сохраните уже выведенные слова, оторвите любые ветки BFS, которые повторяют уже выведенные слова.   -  person G. Bach    schedule 05.03.2015
comment
Какое бы решение вы ни выбрали, не запускайте его на a+.   -  person Sebastian Redl    schedule 05.03.2015
comment
Спасибо G.Bach и Sebastian. Проблема решена.   -  person Nilutpal Borgohain    schedule 06.03.2015
comment
Комментарий: мне удалось разбить строки, разделенные запятыми, и запустить рекурсивный алгоритм, но продукты печатаются в обратном порядке. был отредактирован в вопросе ОП. Я откатил это и поместил здесь, чтобы сделать вопрос более понятным для будущих читателей.   -  person Jonathan Mee    schedule 09.03.2015


Ответы (1)


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

  1. Создайте рекурсивную функцию, которая извлекает строку между первым набором скобок: https://stackoverflow.com/a/28863720/2642059
  2. В функции разделите эти строки на ',' на vector<string> и верните их: https://stackoverflow.com/a/28880605/2642059
  3. Перед возвратом теста, если необходимо выполнить рекурсию из-за вложенной скобки, к возвращаемому результату должна быть добавлена ​​одна строка для каждой возможной комбинации, возвращаемой из рекурсивных функций.

ИЗМЕНИТЬ:

Скажем, моя входная строка была "(bl(ah,eck,le),yap)"

  • Первая функция будет извлекать string: "bl(ah,eck,le),yap"
  • Before returning it would search for nested parenthesis, this would cause it to recurse:
    • The second function would extract the string: "ah,eck,le"
    • Перед возвратом он будет искать вложенные скобки и не найдет их.
    • Это вернет vector<string>: ["ah", "eck", "le"]
  • Первая функция теперь будет содержать: "bl["ah","eck","le"],yap"
  • Он не найдет больше круглых скобок для извлечения, поэтому он перейдет к расширению всех внутренних комбинаций: "["blah","bleck","blle"],yap"
  • Теперь он мог разделить строку и вернуть: ["blah", "bleck", "blle", "yap"]

Возврат из вашей первой функции - это ваш результат.

ИЗМЕНИТЬ:

Рад, что вы решили эту проблему, я написал автомат с двумя состояниями, чтобы решить эту проблему, поэтому я решил опубликовать его здесь для вашего сравнения:

const char* extractParenthesis(const char* start, const char* finish){
    int count = 0;

    return find_if(start, finish, [&](char i){
        if (i == '('){
            count++;
        }
        else if (i == ')'){
            count--;
        }
        return count <= 0; });
}

vector<string> split(const char* start, const char* finish){
    const char delimiters[] = ",(";
    const char* it;
    vector<string> result;

    do{
        for (it = find_first_of(start, finish, begin(delimiters), end(delimiters));
            it != finish && *it == '(';
            it = find_first_of(extractParenthesis(it, finish) + 1, finish, begin(delimiters), end(delimiters)));
        auto&& temp = interpolate(start, it);
        result.insert(result.end(), temp.begin(), temp.end());
        start = ++it;
    } while (it <= finish);
    return result;
}

vector<string> interpolate(const char* start, const char* finish){
    vector<string> result{ 1, string{ start, find(start, finish, '(') } };

    for (auto it = start + result[0].size();
        it != finish;
        it = find(++start, finish, '('),
        for_each(result.begin(), result.end(), [&](string& i){ i += string{ start, it }; })){
        start = extractParenthesis(it, finish);

        auto temp = split(next(it), start);
        const auto size = result.size();

        result.resize(size * temp.size());

        for (int i = result.size() - 1; i >= 0; --i){
            result[i] = result[i % size] + temp[i / size];
        }
    }
    return result;
}

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

В любом случае вы можете назвать это так:

const char test[] = "((a,b,c)o(m,v)p,b)";
auto foo = interpolate(begin(test), end(test));

for (auto& i : foo){
    cout << i << endl;
}
person Jonathan Mee    schedule 04.03.2015
comment
Не могли бы вы дать псевдокод или подробный номер шага. 3 - person Nilutpal Borgohain; 04.03.2015
comment
@NilutpalBorgohain Я немного расширил ответ, но, как уже упоминалось, это потребует некоторой работы. Это плохой вопрос, потому что на самом деле вы просите кого-то другого сделать вашу работу за вас. Если у вас есть дополнительные вопросы, я рекомендую начать работу над этим, и когда у вас будет что показать, спросите, как вы могли бы исправить любую проблему, с которой вы столкнулись, в качестве нового вопроса. - person Jonathan Mee; 04.03.2015
comment
Спасибо, Джонатан, проблема решена. - person Nilutpal Borgohain; 06.03.2015
comment
@NilutpalBorgohain Отличная работа, мужик! Это была забавная проблема. Мы могли бы получить несколько (больше) голосов против за публикацию решения вопроса без приложенной работы, но я подумал, что вам будет полезно просмотреть мою работу. Дайте мне знать, если у вас есть вопросы. Кроме того, если этот ответ решил вашу проблему, нажмите на галочку рядом с ним. - person Jonathan Mee; 06.03.2015