2011-11-14 9 views
1

を探す私は問題を抱えている:私は、文字列s1の内の文字列S2(またはcharの配列)からの最初の出現に任意のシンボルを見つける必要があります。他の文字列内の文字列の任意のシンボルの最初の出現

この目的のための標準機能はありますか?存在しない場合、この問題の良い実装は何ですか? | S2 |(もちろん私はS2からのすべての文字のためにのindexOfを実行することができますが、唯一の最後のシンボルは、S1で発生した場合、我々はS1を介して実行しなければならないので、これは、優れたアルゴリズムのように見えるdoes't私は答えを得る前に-1回)。

ありがとうございました!

+0

Nope; Java Stringクラスにはこれと似たものはありません。あなたが記述するアルゴリズムよりも優れたアルゴリズムを想像できますか? – maerics

+2

私は文字列s2の文字を[正規表現](http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html)にパックします。 'a | b | c | d'(特殊文字をエスケープする必要があります)、Matcher.find(..)を使用して最初のオカレンスを取得します。 –

+0

@maerics私はそれがより速いとは思わない。そのような正規表現を使用すると、文字列を1回だけ反復する必要があります。 – Paulpro

答えて

5

は、一定時間のルックアップ・データ構造(例えばHashSet)にs2からすべての文字を置きます。 s1の各文字を繰り返し、データ構造にその文字が含まれているかどうかを確認してください。

大雑把(未テスト):

public int indexOfFirstContainedCharacter(String s1, String s2) { 
    Set<Character> set = new HashSet<Character>(); 
    for (int i=0; i<s2.length; i++) { 
    set.add(s2.charAt(i)); // Build a constant-time lookup table. 
    } 
    for (int i=0; i<s1.length; i++) { 
    if (set.contains(s1.charAt(i)) { 
     return i; // Found a character in s1 also in s2. 
    } 
    } 
    return -1; // No matches. 
} 

あなたが記述のアルゴリズムでO(n^2)とは対照的に、このアルゴリズムはO(n)です。

3

あなたが探しているものはApache StringUtilsのindexOfAnyです。

実装があるように見えます:

public static int indexOfAny(String str, char[] searchChars) { 
    if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) { 
    return -1; 
    } 
    for (int i = 0; i < str.length(); i++) { 
    char ch = str.charAt(i); 
     for (int j = 0; j < searchChars.length; j++) { 
     if (searchChars[j] == ch) { 
      return i; 
     } 
     } 
    } 
    return -1; 
    } 
+0

リニア検索? Ow、 'searchChars'が決して大きくないことを確認してください。私は、Apacheがもっと洗練された何かをやろうと思っていました。 –

3

この文脈でシンボルとはどういう意味ですか?単なるJavaの16ビットのcharなら、簡単です。考えられるすべての値についてルックアップテーブル(配列)を作成し、それらがs2に現れるかどうかを示します。次に、s2のシンボルが見つかるまで、またはs1の終わりに到達するまで、s1を実行します。 シンボルがUnicodeのコードポイントである場合は、より複雑ですが、上記の方法で詳細を確認する必要があるかどうかを調べることができます。正規表現の使用

+0

あなたは、s2の文字に対応する要素だけがtrueに設定されている2^16ブール値の配列を初期化するでしょうか? (面白いアイデア、私はHashSetもほぼ同様に実行できると思う) –

+0

@AndreHolznerはい、それは考えです。2^16は十分に小さいので、HashSetのような空想的なものを使用する必要はありません。単純な配列がそうするでしょう。私はJVMについて十分に精通していませんが、CではL2(通常のハードウェアの場合)に快適にフィットするため、より速いと確信しています。 'char'は20ビット以上だったので、配列が大きすぎるので、間違いなくある種のセットになります。 –

+0

キーのドメインは2^16と小さいので、これは良い答えです。 – javadba

4

public static void main(final String[] args) { 
     final String s1 = "Hello World"; 
     final String s2 = "log"; 

     final Pattern pattern = Pattern.compile("[" + Pattern.quote(s2) + "]"); 
     final Matcher matcher = pattern.matcher(s1); 
     if (matcher.find()) { 
     System.out.println(matcher.group()); 
     } 
    } 
+0

パターンをコンパイルする前に特殊文字をエスケープする必要があります。 'Pattern.quote(..)'を使用してください。http://stackoverflow.com/questions/60160/how-to-escape-text-for-regular-expression-in-java –

+0

ええ、この回答はおそらく公正が必要です頑強になるまでの量。ハイフンを含む文字列も私が思ういくつかの問題を引き起こすでしょう。 –

関連する問題