2011-07-13 17 views
0

我目前正在爲一個類創建一個項目,以創建一個TextLine類,該類表示必須表示爲一個字符數組的文本行。我不允許通過間接或直接以任何方式使用字符串類來表示TextLine對象,但是,我可以使用它來處理參數。允許indexOf在Java中多次檢查匹配

對於其中一種方法,我應該將一個字符串作爲參數的參數,它也是TextLine對象的一個​​片段,然後返回此片段中第一次出現片段的索引位置TextLine或-1,如果找不到片段。

現在,我試圖找出indexOf方法,但我的問題是,我的方法只檢查一次起點。因此,如果TextLine對象的字母第一次與該片段的字母不匹配,但在對象的其他位置存在另一個匹配,則該方法不會檢查該起始點。

例如,假設我輸入penplay作爲TextLine,然後我輸入play作爲片段。顯然,在TextLine中發生了遊戲,但是我的indexOf方法所做的是,它在索引0處檢查來自penplay的第一個p,然後繼續查看以下字母是否與遊戲長度匹配,並且如果它不,它返回-1。任何想法如何讓算法繼續尋找另一個起點?

這就是我對我的代碼:

public int indexOf(String fragment){ 

char[] temp = fragment.toCharArray(); 

int j = 0; 
for(int i = 0; i < someText.length; i++){ 
    while(someText[i] == temp[j]){ 

     for(j = 1; j < temp.length; j++){ 
      if(temp[j] != someText[i+j]){ 
       return -1; 
      } 
     } 

     return i; 

    } 
} 

return -1; 

} 
+0

你自己的問題應該避讓你:「允許算法繼續搜索」意味着你需要另一個循環,因爲答案提示。最簡單的,即使不是最乾淨的形式也只是一個嵌套在for中嵌套的for。 –

+1

給出的答案看起來都可以接受,但您可能想花幾分鐘時間學習Boyer-Moore字符串搜索算法。這是相當簡單的,很快做這種事情:http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm –

+0

@Kevin偉大的鏈接!很有意思。 –

回答

4

你特殊殼體內的第一個字符,當沒有必要。基本上,你需要說:

  • 對每個可能的起始字符...
    • 是否整個fragment比賽開始,該名候選人的位置?

因此,像:

// Only deal with *viable* starting points 
for (int i = 0; i < someText.length - temp.length; i++) { 
    boolean found = true; 
    for (int j = 0; j < temp.length && found; j++) { 
     if (temp[j] != someText[i + j]) { 
      found = false; 
     } 
    } 
    if (found) { 
     return i; 
    } 
} 
return -1; 

這可以通過提取內環進行重構:

for (int i = 0; i < someText.length - temp.length; i++) { 
    if (textMatches(temp, i)) { 
     return i; 
    } 
} 
return -1; 

... 
// TODO: Javadoc to explain parameters :) 
private boolean textMatches(char[] chars, int startingIndex) { 
    for (int i = 0; i < chars.length; i++) { 
     if (chars[i] != someText[i + startingIndex]) { 
      return false; 
     } 
    } 
    return true; 
} 
+0

我不太明白這段代碼。你能爲我提供意見嗎?謝謝。 – thinhtvu

+0

@thinhtvu:我在答案的開頭解釋了它。分別測試每個潛在的起點 - 想想它是什麼意思,它是從一個特定的起點匹配。 –

1

你有它設置的方式似乎適合作爲一種doesStringExistAtIndex(j, fragment)功能。由於返回-1,如果字符串不第一個索引存在,你可以做這樣的事情:

//assuming that "this" is the subject that you are searching in 
public int indexOf(String fragment){ 
    for(int i=0; i<this.length; ++i){ 
    if(doesStringExistAtIndex(i, fragment)) 
     return i; 
    } 
    return -1; 
} 
+0

你的循環邊界是錯誤的 - 如果你試圖在「這個字符串可能很長但仍然很小」中找到「small」,那麼在到達位置5之後你不想停止尋找...... –

+0

我已經編輯了循環邊界,假設'this.length'是你正在搜索的字符串的長度(當你長度爲5時,永遠不會考慮優化搜索「小」)。 – Dylan

+0

正確 - 它的確意味着你的'doesStringExistAt'方法需要小心,請注意你... –

0

不知道這是你想要的,但我基本上寫了一個方法的indexOf。我做了一些測試,似乎在我做的一些測試中工作得很好。當然,它看起來不同,因爲我想讓測試變得更容易,但是如果您決定使用它,它應該在30秒或更短時間內進行轉換。

public int indexOf(String fragment, String source) 
{ 
    char[] temp = fragment.toCharArray(); 
    char[] someText = source.toCharArray(); 

    outer : for(int i = 0; i <= someText.length - temp.length;i++) //stops looping because why loop after the fragment is longer than the source we have left when its impossible to find 
    { 
     if(someText[i] == temp[0]) //if the first characters are the same 
     { 
      int q = 0; 
      while(q < temp.length) //loop through the fragment 
      { 
       if(someText[i+q] != temp[q]) //if the characters are not the same, stop, and go to the next character of the source. Don't return anything 
       { 
        continue outer; //continues the loop labeled 'outer' (e.g. outer : for(...)) 
       } 
       q++; //increment index since they both match 
      } 
      return i; //fragment and some part of the source matched since it reached here. Return the index of the first character 
     } 
    } 
    return -1; //reached here because nothing was found :(return -1 
} 

編輯0添加的行評論

+0

這與我除了while循環之外基本相同。這對我的問題沒有幫助。謝謝你嘗試! – thinhtvu