0

したがって、問題は、文字列内のすべての文字が特定の正規表現の一致に含まれるかどうかを判断することです。または、別の言い方をすると、特定の正規表現の一致に含まれる可能性のあるすべての文字位置のセットに、文字列内のすべての文字位置が含まれる場合です。

私の考えは、次のようなことをすることです:

boolean matchesAll(String myString, Matcher myMatcher){
    boolean matched[] = new boolean[myString.size()];
    for(myMatcher.reset(myString); myMatcher.find();)
        for(int idx = myMatcher.start(); idx < myMatcher.end(); idx++)
            matched[idx] = true;

    boolean allMatched = true;
    for(boolean charMatched : matched)
        allMatched &= charMatched;

    return allMatched
}

しかし、これを行うためのより良い方法はありますか?

また、これを書いているときに、次のような場合、それは私が望むことをしないことに気づきました。

matchesAll("abcabcabc", Pattern.compile("(abc){2}").matcher()); //returns false

Matcher最後の一致の最後から開始してのみ一致を試みるためです。3 番目の位置でマッチャーを開始するabcと、一致に 3 番目が含まれる可能性があるため、true を返す必要があります。

boolean matchesAll(String myString, Matcher myMatcher){

    boolean matched[] = new boolean[myString.size()];
    boolean allMatched = true;

    for(int idx = 0; idx < myString.size() && myMatcher.find(idx);
            idx = myMatcher.start() + 1) {

        for(int idx2 = myMatcher.start(); idx2 < myMatcher.end(); idx2++)
            matched[idx2] = true;
    }

    boolean allMatched = true;
    for(boolean charMatched : matched)
        allMatched &= charMatched;

    return allMatched;
}

このコードをより良く、より速く、より読みやすくする方法はありますか?

4

2 に答える 2

2

質問を正しく理解しているかどうかはわかりませんが、2 つの回答があります。

  1. find() の代わりに Pattern.matcher(str2match).matches() メソッドを呼び出します。一発で真の戻り値が返され、文字列全体が一致したかどうかがわかります。
  2. reg exp の前に "^" (文字列の先頭) を追加し、正規表現を "Pattern.compile(str)" する前に末尾 (文字列の末尾) に "$" を追加します。

2 つのソリューションを組み合わせることもできます。クラスの例を次に示します。これを AllMatch.java にコピーし、「javac AllMatch.java」でコンパイルして、「java AllMatch」として実行できます (CLASSSPATH に「.」があると仮定します)。よりエレガントなソリューションを選択してください:) 明けましておめでとうございます!

import java.util.regex.Pattern;

パブリック クラス AllMatch {

private Pattern pattern;

public AllMatch (String reStr) {
    pattern = Pattern.compile ("^" + reStr + "$");
}

public boolean checkMatch (String s) {
    return pattern.matcher(s).matches();
}

    public static void main (String[] args) {
    int n = args.length;
    String  rexp2Match = (n > 0) ? args[0] : "(abc)+",
        testString = (n > 1) ? args[1] : "abcabcabc",
        matchMaker = new AllMatch (rexp2Match)
                .checkMatch(testString) ? "" : "un";
    System.out.println ("[AllMatch] match " + matchMaker +
                "successful");
    }

}

于 2013-01-01T17:47:59.463 に答える
1

これは機能します:

private static boolean fullyCovered(final String input,
    final Pattern pattern)
{
    // If the string is empty, check that it is matched by the pattern
    if (input.isEmpty())
        return pattern.matcher(input).find();

    final int len = input.length();
    // All initialized to false by default
    final boolean[] covered = new boolean[len];

    final Matcher matcher = pattern.matcher(input);

    for (int index = 0; index < len; index++) {
        // Try and match at this index:
        if (!matcher.find(index)) {
            // if there isn't a match, check if this character is already covered;
            // if no, it's a failure
            if (!covered[index])
                return false;
            // Otherwise, continue
            continue;
        }
        // If the match starts at the string index, fill the covered array
        if (matcher.start() == index)
            setCovered(covered, index, matcher.end());
    }

    // We have finished parsing the string: it is fully covered.
    return true;
}

private static void setCovered(final boolean[] covered,
    final int beginIndex, final int endIndex)
{
    for (int i = beginIndex; i < endIndex; i++)
        covered[i] = true;
}

実行するのはおそらくそれほど速くはありませんが、読みやすいと思います;) また、.find(int)マッチャーをリセットするので、これは安全です。

于 2013-01-01T17:53:41.240 に答える