5

指定されたパターンに一致する入力文字列内のすべての部分文字列を取得しようとしています。

例えば、

与えられた文字列: aaxxbbaxb
パターン: a[az]{0,3}b
(私が実際に表現したいのは、a で始まり b で終わるすべてのパターンですが、その間に最大 2 つのアルファベットを含めることができるということです)

私が望む正確な結果(インデックス付き):

aaxxb: インデックス 0~4
axxb: インデックス 1~4
axxbb: インデックス 1~5
axb: インデックス 6~8

しかし、 and を使用して Pattern クラスと Matcher クラスを実行するPattern.compile()Matcher.find()、次のような結果しか得られません。

aaxxb : インデックス 0~4
axb : インデックス 6~8

これは私が使用したコードです。

Pattern pattern = Pattern.compile("a[a-z]{0,3}b", Pattern.CASE_INSENSITIVE);
Matcher match = pattern.matcher("aaxxbbaxb");
while (match.find()) {
    System.out.println(match.group());
}

pattern に一致するすべての文字列を取得するにはどうすればよいですか?

もちろん、効率的である限り、Pattern クラスと Matcher クラスを使用する必要はありません :)

4

3 に答える 3

3

(参照: Java 正規表現に一致するすべての重複する部分文字列)

これが私が思いついた完全な解決策です。オリジナルの正規表現でゼロ幅のパターンや境界などを扱うことができます。テキスト文字列のすべての部分文字列を調べ、最初と最後に適切な数のワイルドカードをパターンに埋め込むことによって、正規表現が特定の位置でのみ一致するかどうかを確認します。私が試したケースではうまくいくようですが、広範なテストは行っていません。それは間違いなく、それができるよりも効率が悪いです。

  public static void allMatches(String text, String regex)
  {
    for (int i = 0; i < text.length(); ++i) {
      for (int j = i + 1; j <= text.length(); ++j) {
        String positionSpecificPattern = "((?<=^.{"+i+"})("+regex+")(?=.{"+(text.length() - j)+"}$))";
        Matcher m = Pattern.compile(positionSpecificPattern).matcher(text);

        if (m.find()) 
        {   
          System.out.println("Match found: \"" + (m.group()) + "\" at position [" + i + ", " + j + ")");
        }   
      }   
    }   
  }
于 2012-07-05T18:42:16.690 に答える
1

実際には、入力文字列で文字列 ab、a_b、および a__b を検索しています。ここで、_ は値が気にならない非空白文字を示します。

それが3つの検索対象です。これを行う最も効率的な方法は、 Knuth-Morris-Prattアルゴリズムのような検索アルゴリズムをいくつか変更して使用することです。実際には、疑似コードは次のようになります。

for i in 0 to sourcestring.length
    check sourcestring[i] - is it a? if so, check sourcestring[i+x] 
       // where x is the index of the search string - 1
    if matches then save i to output list
    else i = i + searchstring.length

明らかに、位置が一致している場合は、部分文字列の内部文字をチェックして、アルファベット順であることを確認する必要があります。

検索語ごとに 1 回ずつ、アルゴリズムを 3 回実行します。パターン マッチングを使用して検索を試みるよりもはるかに高速であることは間違いありません。

編集 - 申し訳ありませんが、質問を正しく読んでいませんでした。正規表現を使用する必要がある場合、上記は機能しません。

于 2011-09-06T10:54:33.407 に答える
0

あなたができることの1つは次のとおりです。

  • 4文字以上の可能なすべての部分文字列を作成します(文字列が大きい場合は頑張ってください)
  • これらの部分文字列ごとに新しい Matcher を作成します
  • find() の代わりに match() を実行する
  • 部分文字列の相対オフセットとマッチャー情報から絶対オフセットを計算します
于 2011-09-06T10:38:56.557 に答える