我製作了KMP算法失敗表的實現。生成此數組時產生無限循環
kmp s = b
where a = listArray (0,length s-1) s
b = 0:list 0 (tail s)
list _ [] = []
list n (x:xs)
| x==a!n = (n+1):list (n+1) xs
| n > 0 = list (b!!(n-1)) (x:xs)
| otherwise = 0:list 0 xs
b
是一個列表,並b!!(n-1)
最後一行是緩慢的,因此,我要加快速度,也做了以下內容。
kmp s = b
where a = listArray (0,length s-1) s
t = listArray (0,length s-1) b
b = 0:list 0 (tail s)
list _ [] = []
list n (x:xs)
| x==a!n = (n+1):list (n+1) xs
| n > 0 = list (t!(n-1)) (x:xs)
| otherwise = 0:list 0 xs
注意,唯一的區別是由t!
取代b!!
並聲明t
是從b
產生的陣列。
對於相同的輸入,原始代碼具有正確的輸出,但新輸出只輸出<<loop>>
。
如何解決這個問題?
該算法的教科書命令版本(參見例如CLRS)僅使用數組的懶惰構造直接轉換爲快速版本(無「O(n^2)」查找)。另外,Bird的書「功能算法設計珍珠」有一個KMP的推導,它不使用數組,但是這肯定與OP的算法看起來有很大的不同。 – Fixnum
@Fixnum'STArray'版本中沒有O(n2),它是我知道的教科書算法的未優化版本,非常線性。當然,將數組轉換爲一個列表後效率不高,應該使用數組[實際上,應該從開始使用unboxed數組]。 –
對不起!我指的是OP對列表索引的抱怨,我錯誤地認爲這會導致漸近放緩。我只是想指出,你可以消除沒有可變數組的'(!!)',並且對OP代碼的侵入性更小)。 – Fixnum