2013-07-14 41 views
3

有一串話來了,這是非常大的。隨着單詞不斷出現,可能會要求您告知是否在已經看到的流中發生了短語在不同的時間可能有多個這樣的查詢。如何以最佳方式返回短語是否出現在單詞流中?

例如,假設看到到現在的話流是:

你好這裏的世界是另一個程序員

然後,它要求告訴短語here is another是否已經看到或不,在這種情況下是這樣。

如何優化返回?

我一直試圖在使用圖形的建設和查詢時做BFS解決工作,但它帶來了兩個問題:

  • 首先,是最佳的,我也有存儲話=>圖中的節點地址對在一個散列表中。

  • 其次,當存在循環,那麼算法失敗作爲流中:a b c d a b c e

推薦爲需求的最佳解決方案。

+0

你會考慮任何這些解決方案的最佳? http://stackoverflow.com/questions/6606581/find-repeated-word-in-infinite-stream-of-words –

+0

@OzzieGooen你提到的問題是,雖然你可能會發現相關的,是完全不同的,因爲它要求報告只能使用散列表處理的重複項。 – Sankalp

+0

既然你不知道查詢語句是什麼,如果只有一個查詢,那麼假設你有一個流是沒有意義的;你必須記住迄今爲止所看到的所有數據。或者,您可能會在不同時間收到多個查詢,而流仍在進行中?我猜我可以理解。或者你可能想要做一些類似連續線性時間工作的流,因爲當查詢進來時,你可以比O(n)更快地解決問題? – user2566092

回答

1

您可以查看「在線構建後綴樹」,並找到一個由Ukkonen處理流的算法,並且在每個字符處理完成後,您的流總是有一個後綴樹,並且運行時間和空間爲O( n)如果你迄今看過n個字符。然後,每次給出查詢短語時,都可以使用子字符串匹配算法爲後綴樹查找給定查詢短語的所有匹配,並且如果查詢短語具有長度,則查詢時間爲最佳O(m)以查找匹配米

+0

這似乎沒有回答OP的問題。 –

+0

對不起,你能解釋一下後綴樹在這裏會有幫助嗎?如果您正在暗示字符串匹配,那麼它如何將查詢的複雜度降低到查詢字符串的長度? – Sankalp

1

由於您正在接收文本正文以流式方式進行搜索,因此對「預處理」文本以進行更有效的搜索沒有任何意義。這是C#中的一種高效實現,它處理要以流式方式搜索的文本。

static IEnumerable<int> Search(string text, string query) 
{ 
    var D = new Dictionary<int, int>(); 
    //Loop invariant: D[i] == j iff text[i..(i+j)] == query[0..j] 
    //    for all pairs (i,j) in D 
    for (int i = 0; i < text.Length; i++) 
    { 
     foreach (var k in D.Keys.ToList()) 
     { 
      D[k] = D[k] + 1; 
      if (D[k] == query.Length) 
      { 
       yield return k; 
       D.Remove(k); 
      } 
      else if (text[i] != query[D[k]]) 
      { 
       D.Remove(k); 
      } 
     } 
     if (text[i] == query[0]) 
      D.Add(i, 0); 
    } 
    foreach (var k in D.Keys) 
    { 
     if (D[k] == query.Length) 
      yield return k; 
    } 
} 

基於流式的版本可以如下實現。我認爲流式結束的情況可能無法正確處理,但即使在這種邊緣情況下,您也應該能夠將這個想法適應於某種可行的方式。

class SearcherState 
{ 
    public Dictionary<int, int> D = new Dictionary<int, int>(); 
    public int i = 0; 
} 

static Func<char, int?> Searcher(string query) 
{ 
    var state = new SearcherState(); 
    return c => 
    { 
     int? result = null; 
     foreach (var k in state.D.Keys.ToList()) 
     { 
      state.D[k] = state.D[k] + 1; 
      if (state.D[k] == query.Length) 
      { 
       result = k; 
       state.D.Remove(k); 
      } 
      else if (c != query[state.D[k]]) 
      { 
       state.D.Remove(k); 
      } 
     } 
     if (c == query[0]) 
      state.D.Add(state.i, 0); 
     state.i++; 
     return result; 
    }; 
} 
+0

這至少需要Omega(n)時間,其中流已經產生了n個字符。對於大n和相當小的查詢,每次查詢時在查詢時間內都有n是不可接受的。 – user2566092

+0

@ user2566092提出的問題是,要搜索的文本正在流式傳輸並在流式傳輸時進行搜索。例如,你不能提前建立一個系統。此外,似乎只有一個指定的查詢字符串。 OP沒有說會有多個查詢。 –

+0

根據問題編寫的方式,在不同的時間可以有多個查詢。但是,如果只有一個查詢,並且如果用戶不介意在查詢進入時等待一段時間以獲取答案,即使有可用的cpu循環在流進來時被浪費,然後我同意您的答案可以接受。真正的問題是數據流進入的速度有多快,因此可以確定在線線性時間預處理是否可以跟上,然後在進入時查詢基本上不會花費時間。 – user2566092

相關問題