2011-11-14 152 views
1

串的任何元件的第一次出現我有一個問題:我需要在字符串S1找到從字符串S2(或炭的陣列)的任何符號第一次出現。查找其他字符串

是否有用於此目的的標準功能?如果沒有,這個問題有什麼好的實現? (當然,我可以運行的indexOf從我的每S2字符,但這個開不似乎是一個很好的算法,因爲如果在S1只發生在最後一個符號,我們必須通過S1運行| S2 | -1次我纔得到答案)。

非常感謝!

+0

不是; 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我懷疑它更快。使用這樣的正則表達式,只需要在字符串中迭代一次。 – Paulpro

回答

5

把所有字符從s2成一個常數時間的查找數據結構(例如HashSet)。遍歷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)在你所描述的算法不是O(n^2)

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

線性搜索?噢,最好確保'searchChars'永遠不會很大。我認爲Apache會做一些更復雜的事情。 –

3

什麼是符號在這種情況下是什麼意思?如果它只是一個16位Java char,那很簡單。爲所有可能的值創建一個查找表(數組),指出它們是否出現在s2中。然後通過s1,直到找到s2中的符號或者到達s1的末尾。如果一個符號是一個Unicode代碼點,它更復雜,但上面給出了一個方法來找出你需要仔細看看。

+0

你的意思是,你將初始化一個2^16布爾數組,其中只有對應於s2中的一個字符的元素被設置爲true? (有趣的想法;我認爲HashSet可以執行得幾乎一樣) –

+0

@AndreHolzner是的,這就是主意。2^16足夠小,所以不需要使用像HashSets這樣的花哨的東西,簡單的數組就可以做到。我對JVM不夠熟悉,但在C中,我相當確信它的速度更快,因爲它適合於L2(正常硬件)。如果字符數爲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

是的,這個答案可能需要一個公平的增加的數量要強勁。包含連字符的字符串也會導致我認爲的一些問題。 –