我試圖找到儘可能最快的方式來搜索字符串Text
中的子字符串。下面是所需的輸出:如何在`Text`中以非常快的速度搜索子字符串?
findSubstringIndices :: Text -> Text -> [Int]
findSubstringIndices "asdfasdf" "as" == [0, 4] -- 0-indexed
findSubstringIndices "asdasdasdasd" "asdasd" == [0, 3, 6] -- matches can overlap
在我的應用程序,則子是一個固定的6字母的單詞,而是要搜索的字符串是很長的(比方說超過3十億個字母)。我目前的做法是使用KMP
包:
import Data.Text.Lazy as T
import Data.Algorithms.KMP as KMP
findSubstringIndices a b = KMP.match (KMP.build $ T.unpack b) $ T.unpack a
但它似乎是一個巨大的由Text
緊湊的浪費。有沒有(最好簡潔)的方式來做到這一點沒有unpack
ing?
我知道Text
中有一個叫做breakOnAll
的函數,但是它不符合我允許重疊匹配的要求。
編輯:每@ReidBarton的建議下,我實現了不需要unpack
,這確實是一個速度更快的版本。但我不確定這是否是最快的。
findSubstringIndicesC t a b = let (l, r) = T.breakOn b a in case r of
"" -> []
_ -> T.length l : findSubstringIndicesC (t + T.length l + 1) (T.tail r) b
findSubstringIndices = findSubstringIndicesC 0
你預計會有很多比賽嗎?一個簡單的方法是使用'breakOn',然後從結果的第二部分丟棄一個字符並重復。 –
@ReidBarton:這是一個想法。我有點擔心文檔說「如果你需要重複地用一個子串打斷一個字符串(例如,你想打破每個子串的實例),請改用breakOnAll,因爲它具有較低的啓動開銷。」這是否意味着重複使用此功能不可取? – trVoldemort
嗯,是的,我認爲每個搜索都有一些額外的啓動開銷。這就是爲什麼我問你是否期望找到大量的匹配,或者只是少數,在這種情況下額外的開銷不太可能成爲問題。無論如何,第三方軟件包中可能會有更好的解決方案。 –