どのようにJavaで正規表現を使用して文字列内の文字セットの最後の出現を見つけるには?

darklearner07:

私は、文字列内の文字のセットの最後のインデックスを見つける必要があります。なる文字のセットを考えてみましょX、Y、Zとして、文字列Vereadorルイス・ポーリーホーム、私のように、インデックスを必要とする18

だから、インデックスを見つけるために私がして、パターン作成したDOTALLのフラグと貪欲数量詞を通り(?S)*(X | Y | Z)。 パターンは、その文字列(複数行)に適用されると、私はスタートグループからインデックスを見つけることができます。コード:

int findIndex(String str){
  int index = -1;
  Pattern p = Pattern.compile("(?s).*(x|y|z)");
  Matcher m = regex.matcher(str);
  if(m.find()){
    index = m.start(1);
  }
  return index;
}

一致がある場合には、正確な値を返していると予想しました。

一致がない場合でも、それはあまりにも長い時間がかかる(600000の文字について17分)、それは貪欲一致するように。

私は他の数量でみましたが、所望の出力を得ることができません。誰もが任意のより良い正規表現を参照することができだから?

PS:私はまた最後からコンテンツを横断してすぐに仕事をすることができます正規表現でいくつかのより良い方法があるindex.But Iの希望を見つけることについて考えることができます。

チャールズDowbecki:

問題と入力の大きさとパターンの複雑さに依存します最善の方法を解決するには、いくつかの方法があります。

  1. 入力文字列と、おそらく、パターン、非複雑なパターンのために、このかもしれない作業を逆にします。残念ながら、java.util.regex右から左へのパターンに一致するようにすることはできません。

  2. 代わりに、貪欲数量詞を使用することの単にパターンとループと一致しMatcher.find()、最後の発生が検出されるまで。

  3. より良いパフォーマンスなどで別の正規表現エンジンを使用し、Javaの線形時間の正規表現マッチング:RE2 / Jを

オプション2は、あなたのケースのために十分に効率的ではない場合、私はRE2 / Jをしようとすることをお勧めしたいです。

このようPCRE、PerlやPythonなど、Javaの標準の正規表現パッケージ、のjava.util.regex、および他の多くの広く使われている正規表現パッケージは、バックトラックの実装戦略を使用:するときのパターンのプレゼントのような二つの選択肢a|b、エンジンはサブパターンと一致するようにしようとするa最初の、その利回りマッチしない場合、それは、入力ストリームをリセットし、一致しようとしますb代わりに。

そのような選択肢が深くネストされている場合は、入力が一致するかどうかを検出することができます前に、この戦略は、入力データを乗り越えの指数番号が必要です。入力が大きい場合、その実行中の時間、宇宙の寿命を超えてしまうパターンを構築することは容易です。そのようなWebアプリケーションのユーザーとして信頼できないソースから正規表現パターンを、受け付けた場合これは、セキュリティ上のリスクを作成します。

対照的に、RE2アルゴリズムは、非決定性有限オートマトンを用いて、入力データに対する単一のパスで同時にすべての一致を探ります。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=173471&siteId=1