2

データベースにフレーズのリスト(フレーズは1つ以上の単語で構成されている場合があります)と入力文字列があります。これらのフレーズのどれが入力文字列に表示されるかを調べる必要があります。

Javaでそのようなマッチングを実行する効率的な方法はありますか?

4

4 に答える 4

3

簡単なハックは次のようになります。

  1. 組み合わせたフレーズに基づいて正規表現を作成します
  2. これまでに一致していないフレーズをリストするセットを作成します
  3. findすべてのフレーズが見つかるか、入力の終わりに達するまで繰り返し実行し、残りのフレーズのセットから一致を削除して検索します

そうすれば、入力したフレーズの数に関係なく、入力は1回だけトラバースされます。正規表現コンパイラが複数の選択肢に対して効率的なマッチャーを生成する場合、これにより適切なパフォーマンスが得られるはずです。ただし、これはフレーズと入力文字列、およびJava正規表現エンジンの品質に大きく依存します。

サンプルコード(テスト済みですが、パフォーマンスのために最適化またはプロファイルされていません):

public static boolean hasAllPhrasesInInput(List<String> phrases, String input) {
    Set<String> phrasesToFind = new HashSet<String>();
    StringBuilder sb = new StringBuilder();
    for (String phrase : phrases) {
        if (sb.length() > 0) {
            sb.append('|');
        }
        sb.append(Pattern.quote(phrase));
        phrasesToFind.add(phrase.toLowerCase());
    }
    Pattern pattern = Pattern.compile(sb.toString(), Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(input);
    while (matcher.find()) {
        phrasesToFind.remove(matcher.group().toLowerCase());
        if (phrasesToFind.isEmpty()) {
            return true;
        }
    }
    return false;
}

いくつかの警告:

  • 上記のコードは、単語の部分文字列としてフレーズに一致します。完全な単語のみが一致する必要がある場合は、生成された正規表現に単語の境界( "\ b")を追加する必要があります。
  • 一部のフレーズが他のフレーズのサブストリングである可能性がある場合は、コードを変更する必要があります。
  • 非ASCIIテキストを照合する必要がある場合は、適切なを使用して、の代わりに正規表現オプションPattern.UNICODE_CASEを追加して呼び出す必要があります。toLowerCase(Locale)toLowerCase()Locale
于 2011-05-17T21:58:46.183 に答える
0

これがjavaを使用した解決策です。使用する文字列について何も指定していないので、一般的な例を検討します

Pattern p = Pattern.compile("cat");
        // Create a matcher with an input string
Matcher m = p.matcher("one cat," +" two cats in the yard");
boolean b = m.matches();  // Should return true

お役に立てば幸い

参照: http: //java.sun.com/developer/technicalArticles/releases/1.4regex/

于 2011-05-17T19:49:41.953 に答える
0
sql = "SELECT phrase " + 
  " FROM phrases " + 
  " WHERE phrase LIKE $1";     
PreparedStatement pstmt =  conn.prepareStatement (sql);
// probably repeated, if more than one input:
pstmt.setString (1, "%" + input + "%");
ResultSet rs = pstmt.executeQuery ();

プリペアドステートメントはデータベースに適合するようにチェックされ、繰り返し呼び出される場合は高速であるため、複数の入力がある場合でも、ループで実行される高速である必要があります。

もちろん、すべてのフレーズをRAMやマップにロードすることもできます。準備が遅いので、1つの入力だけでなく、複数の呼び出しがある場合は速くなる可能性があります。しかし、データベースは検索に非常に効率的であることがよくあります。

于 2011-05-17T20:44:54.653 に答える
0

データベースの検索フレーズを、一般的な始まりに基づいてツリーに整理できます。そのツリーのノードに一致させようとしている文字ごとに文字列を分析することができます。

于 2011-05-17T20:51:24.317 に答える