web-dev-qa-db-ja.com

正規表現から文字列への生成

正規表現とインデックスiがあるとします。正規表現に一致する文字列のセットが辞書式順序で並べ替えられていると想定すると、このリストのi要素をどのように取得できますか?

編集:詳細な説明のために、この簡単な例を追加しました。

入力:

regex="[a-c]{1,2}";
index=4;

この場合、この正規表現が一致する文字列の順序付きリストには、次の要素が含まれています。

a
aa
ab
ac
b
ba
bb
bc
c
ca
cb
cc

出力:

acである4番目の要素

ps:与えられた正規表現が無制限の数の文字列にマッチすることが知られています。これは、指定された有限indexの要素を抽出するプロセスに影響を与えません。

4
Mifmif

ケビンの答えは、理論的な観点から正規表現をどのように処理できるかを知る良い出発点でした。これは、ユーザーが特定の正規表現に基づいて文字列を生成できるJavaライブラリを構築するのに役立ちます。ここでこれは私が作成したものです Javaライブラリ 正規表現を使用して文字列を生成するための多くの機能を提供します(ランダム生成、インデックスに基づいて文字列を生成し、すべての文字列を生成します。)チェックしてください- ここ

例:

    Generex generex = new Generex("[0-3]([a-c]|[e-g]{1,2})");

    // generate the second String in lexicographical order that match the given Regex.
    String secondString = generex.getMatchedString(2);
    System.out.println(secondString);// it print '0b'

    // Generate all String that matches the given Regex.
    List<String> matchedStrs = generex.getAllMatchedStrings();

    // Using Generex iterator
    Iterator iterator = generex.iterator();
    while (iterator.hasNext()) {
        System.out.print(iterator.next() + " ");
    }
    // it print 0a 0b 0c 0e 0ee 0e 0e 0f 0fe 0f 0f 0g 0ge 0g 0g 1a 1b 1c 1e
    // 1ee 1e 1e 1f 1fe 1f 1f 1g 1ge 1g 1g 2a 2b 2c 2e 2ee 2e 2e 2f 2fe 2f 2f 2g
    // 2ge 2g 2g 3a 3b 3c 3e 3ee 3e 3e 3f 3fe 3f 3f 3g 3ge 3g 3g 1ee

    // Generate random String
    String randomStr = generex.random();
    System.out.println(randomStr);// a random value from the previous String list
3
Mifmif

正規表現は、有限状態機械に直接マップされます。 FSMからの文字列の生成は、バックトラッキングアルゴリズムを使用すると簡単です。例は、正規表現/ aa?b /の場合です

(start) 0 -- a --> 1 -- a --> 2 -- b --> 3 (accepting and terminal)
                   |                     ^
                   |---------b ----------|

State   Previous char   Input char    Input string     History
  0        null                           --             []
                            a              a         
  1        null                                        [{a,1}]
                            a              aa          [{a,1},{a,2}]
  2        null
                            b             aab          [{a,1},{a,2},{b,3}]
  3        null
         Accepting state, emit 'aab' as valid input
         Terminal state, backtrack
  2          b                             aa          [{a,1},{a,2}]
         No further valid inputs, backtrack
  1          a                             a           [{a,1}]
                            b              ab
  3        null                                        [{a,1},{b,3}]
         Accepting state, emit 'ab' as valid input
         Terminal state, backtrack
  1          b                             a           [{a,1}]
         No further valid inputs, backtrack
  0          a                             --          []
         No further valid inputs, stack empty, terminate
6
kevin cline

正規表現はそれ自体で、「文字列のthislistを入力として与え、このパターンをどのサブセットが計算するか」という質問に答える目的で機能しています。 。逆方向には機能しません。つまり、この正規表現から、それに一致する文字列の生成を開始します。

そうは言っても、これを見てください: https://code.google.com/p/xeger/ 、それはあなたが達成したいことをするはずです(で説明されているようにいくつかの制限があります- https://code.google.com/p/xeger/wiki/XegerLimitations )。

あなたの正規表現が受け入れられた場合、あなたの質問への答えは非常に簡単です、つまり、リストを生成し、インデックスiのアイテムを取得します

3
Bober02

それがあなたにいくらか役立つかもしれない場合に備えて、私はこの答えを提案したいと思います。詳細や小さなエラーがある場合は、コメントを残してください。修正してみます。

  1. まず、正規表現の最小有限状態オートマトンFSAを見てください。
  2. FSAの最初に一致する文字列を見つけます。これは、リジェクト状態に至るすべてのパスを削除し、補助FSAのウォークスルーを開始する補助FSAを作成することで実行できます。各遷移で、入力アルファベットから最初の文字を選択して、最初に一致する文字列を生成するようにします。
  3. 次に、元の正規表現の2番目に一致する文字列を取得する必要があるため、最終状態(accep状態の前)で最後の文字入力(上記の2の最初の一致する文字列)が先行しないように、補助FSAを変更します。受け入れ状態に。これは、エッジ(および状態)を削除するか、エッジを変更して受け入れ状態にすることで実行できます。
  4. 変更された補助FSAの最初に一致する文字列を生成します。これにより、元の正規表現の2番目に一致する文字列が得られます。
  5. I番目の一致する文字列に到達するまで、補助FSAの変更を繰り返します。これは、元の正規表現に一致する文字列です。
2
InformedA