5

文字のセットがあるとします[ABC]。空のセットを除くスーパーセットの任意の順列に一致する正規表現を探しています。

ABC ACB BAC BCA CAB CBA
AB BC AC CB CA BA
A B C

正規表現は(明らかに)空の文字列と一致してはなりません。

ps同じ目的を表現する別の方法は、「セット内の各文字を含む空でない文字列を最大1回一致させる」ことです。

更新:セット[ABC]は単なる例です。実際のセットの方が大きい場合もあります。この質問で、私はの特定の解決策ではなく、「一般的な」解決策を見つけることを望んでいました[ABC]

4

8 に答える 8

6

これは正規表現で解決できると思います。この正規表現を使用します。

/^([ABC])(?!\1)([ABC])?(?!\1|\2)[ABC]?$/

これに関するオンラインデモが必要な場合はお知らせください。

于 2012-04-26T12:08:44.647 に答える
3

あなたの答え(特にanubhavaとcodaddictの)のおかげで、私はこの解決策を見つけることができました、それは一度だけセットをタイプすることができるのでかなりエレガントだと思います:

\b(([ABC])(?!.*\2))+\b

\b完全な単語に一致するために必要です。それらを省略すると、必要なプロパティを尊重するサブワードも見つかります。完全な文字列に一致させるには、明らかに次のようにします。

^(([ABC])(?!.*\2))+$
于 2012-04-26T20:34:40.080 に答える
1

これは正規表現が得意なことではありません。代わりに順列のリストを作成してから、すべての一意のサブストリングを作成することもできます。

何かのようなもの:

def matches(s, characters):
    if len(s) != len(set(s)):
        return False # not unique sequence of characters
    return set(s).issubsetof(set(characters))
于 2012-04-26T12:02:15.537 に答える
1

試す:

([ABC]?)(?!.*\1)([ABC]?)(?!.*\2)[ABC]?

[ABC]?重複する文字を許可しないネガティブ先読みアサーションのチェックを追加して、3回繰り返されます。

これは、入力セットがすべて一意である場合にのみ機能することに注意してください。

それが機能するのを見る

于 2012-04-26T12:05:54.210 に答える
1
"A((B?C?)|(C?B?))|B((A?C?)|(C?A?))|C((A?B?)|(B?A?))"

これはA|B | Cであり、それぞれの後にオプション値のペアを続けることができます

 A(B?C?) matches A, AB,AC and ABC
 A(C?B?) matches A, AC,AB and ACB 

ただし、ACAC、AA、またはACCではありません。最初の文字がBまたはCの場合は同等です。

より長い文字列の場合、これはすぐに醜くなります。より良いアプローチは(擬似コード)です:

 string.sort().matches ("^A?B?C?$") && string.length > 0
于 2012-04-26T13:06:56.043 に答える
0

これを試してください:(更新)

A[BC](?![ABC])|B[AC](?![ABC])|C[AB](?![ABC])|[ABC](?![ABC])|(ABC|ACB|BAC|BCA|CAB|CBA)(?![ABC])

デモ :

http://regexr.com?30pa6

于 2012-04-26T11:57:44.440 に答える
0

これが私のバージョンです:

\b(?=[ABC]{1,3})([ABC]{1})(?:(?!\1)([ABC]{1})(?:(?!\1)(?!\2)[ABC]{1})?)?\b

論理:

  • \b:単語の境界を探す
  • (?=[ABC]{1,3}):A、B、Cのみの値を持つ長さ=3の文字列があるかどうかを先読みしてください
  • ([ABC]{1}):最初の文字に一致し、オプションで
  • (?!\1)([ABC]{1}):次の文字が以前に一致したものと同じでないかどうかを確認します-そうでない場合は、一致し、オプションで一致します
  • (?!\1)(?!\2)[ABC]{1}:次の文字が以前に一致した文字1または2と同じでないかどうかを確認します-そうでない場合は、文字と一致します

この入力に対してテストしたので、非常に信頼できるようです。

AABCC BBCC AB BC AC CB CA BA ABC ABC ACB BAC BCA CAB CBA AAA ABB AAA BBC AA


編集:

あなたが言ったように、文字セットはもっと大きくなる可能性があります。私はあなたの質問のPSアドバイスに従い、これを次のように行います。

  • 許可されたセット内の各文字を保持する配列を導入charsします(文字列を文字に分割します)

  • の配列を取得しinputStringsます(入力文字列を空白またはその他の必要なものに分割します)

  • {のそれぞれstringについてinputStrings

  • かどうかを確認しますstring.length <= inputStrings.length
  • tryMatchリスト内の各文字を現在の入力と照合し、matchesリスト内で見つかった一致の数を保存します
  • リストにエントリが含まれているかどうかを確認してmatchesから、すべてのエントリが==1または0であるかどうかを確認します}
于 2012-04-26T12:23:32.470 に答える
0

OK、私はあなたの質問についてよく考えたと言わなければなりません-あなたは本当に普遍的でカスタマイズ可能なもの(できるだけ多くの要素をサポートするなど)を望んでいるようです-これが私が最も最適だと思うものです解決。

数学の観点から、必要なのは、繰り返しなしで要素のセットのすべての順列を識別することです。


ステップ1 :

セットのすべての順列繰り返して検索します(たとえば、配列に格納します)

[ABC]([ABC]{1,2})?

補足:n要素のセットがあるとしましょう。あなたがしなければならないのは:

[elements]([elements]{1,n-1})?


ステップ2 :

重複する要素ですべての順列をフィルタリングする

PHPのサンプルコード:

<?php

    function strToArray($str)
    {
        $i = 0;

        while (isset($str[$i]))
        {
            $result[$i] = $str[$i];
            $i++;
        }

        return $result;
    }

    function noDuplicates($str)
    {
        if (array_unique(strToArray($str))==strToArray($str)) return true;
        else return false;
    }

    $AAA = "AAA";
    $ABC = "ABC";

    if (noDuplicates($AAA)) echo "$AAA : ok"; else echo "$AAA : not ok\n";
    if (noDuplicates($ABC)) echo "$ABC : ok"; else echo "$ABC : not ok\n";

?>

出力:

AAA : not ok
ABC : ok
于 2012-04-27T08:16:45.497 に答える