2015-05-17 51 views
0

所有子序列在一個程序中,我需要能夠有效地回答下列形式的查詢:尋找從字典

給定一組字符串A和查詢串Q回報所有s∈A使得s爲q的子例如,給定A = {「abc」,「aaa」,「abd」}和q =「abcd」,「abc」和「abd」應該被返回。

有沒有更好的方法比迭代A的每個元素並檢查它是否是q的子序列?

注意:我有STRIPS計劃員或自動計劃員記。 STRIPS策劃師的每個狀態都是一組命題,如{「(room rooma)」,「(at robby rooma)」,「(在ball1 rooma)」}。我想找到適用於特定州的所有地面行動。 STRIPS規劃師的行動基本上由兩部分組成,前提條件和效果(這裏並不真正相關)。先決條件是將一個行動應用到一個國家所需要的一組命題。例如,要應用一個動作「(移動rooma roomb)」,其前提條件{「(room rooma)」,「(room roomb)」,(at robby rooma)}}都必須在該狀態下爲真。

+0

是的 - 你可以從你的集合'A'中建立一個FSM,並且只需要通過'q'並計數/記住你遇到的最終狀態 - 它基本上是解析的詞法分析器 - 是這個作業還是工作面試問題? ;) – Carsten

+0

引用'A'的每個元素並檢查它是否是'q'_的子序列不是一個壞主意。它的複雜性是'O(n2)'。 – Han

+0

感謝您的諮詢! FSM的查詢速度肯定會更快,但我認爲構建它會花費太多。 – user3127171

回答

0

如果您設置一個大,你有很多的疑問,你可以實現一個trie-like structure,其中ñ水平是指性格在字符串n。在您的例子:

trie = { 
    a: { 
     a: { 
      a: { value: "aaa"} 
     }, 
     b { 
      c: { value: "abc"}, 
      d: { value: "abd"} 
     }   
    } 
} 

這將使您通過線索查找匹配的分叉路徑:

function query(trie, q) { 
    s = Set(); 

    if (q.isEmpty()) { 
     if (trie.value) s.add(t.value); 
    } else { 
     s = s.union(query(trie, q[1:])); 

     c = substr(q, 0, 1); 
     if (t[c]) { 
      s = s.union(query(t[c], substr(q, 1)); 
     } 
    } 
    return s; 
} 

Efectively,你將生成所有2 ^米的quesy串子集m字符,但在實踐中,trie非常稀疏,您最終會檢查更少的路徑。

速度收益來自許多查找。構建這個trie比使用暴力查找更昂貴。但是,如果您僅更新設置的唯一一個或有更新設置的手段,您將獲得良好的查找性能。

trie節點的實際數據結構取決於項目可以具有多少個可能的元素。在你的例子中,只有四個字母被使用。如果您的「字母」範圍有限,則可以使用數組。否則,你可能需要一種字典,這可能會使樹在記憶中變得很大。

+0

感謝您的詳細解答。實際上,我也提出了這個想法,但我想知道生成所有2^m子集是否是一個好主意。然而,在閱讀你的解釋後,我終於可以說服自己,這是一條路。 – user3127171

+0

根據你的需要判斷。如果你的設置很小並且查找頻率不高,那麼天真的方式可能沒問題。這種方法的想法是縮短許多可能的2^m路徑。 –