Haskell中的KMP字符串搜索 - 非穷举模式

时间:2018-01-31 16:51:42

标签: string algorithm haskell

您好我尝试在Haskell中实现KMP字符串搜索算法。但是当我尝试运行kmp函数时,它只会说"非详尽的模式"这个功能。无论我多么努力纠正它。我以为我的每一个可能的结果都是隐蔽的。也许我只是失明但我希望有人能在这里帮助我。:

prefix :: String -> [Int]
prefix p = hprefix p p 0

hprefix :: String -> String -> Int -> [Int]
hprefix [] (i:is) int = []
hprefix (p:ps) (i:is) int | (length(i:is)) - (length(p:ps)) == 0 = 0:(hprefix ps (i:is) 0)
                          | p == (head(drop (int) (i:is))) = (int+1):(hprefix ps (i:is) (int+1))
                          | p == i = 1:(hprefix ps (i:is) 1)
                          | otherwise = 0:(hprefix ps (i:is) 0)

hkmp :: String -> String -> [Int]
hkmp p [] = error "leerer Text"
hkmp [] t = error "leeres Pattern"
hkmp p t = kmp p p (take (length p) t) t t

kmp :: String -> String -> String -> String -> String -> [Int]
kmp p (a:as) (b:bs) (t:ts) o | o == [] = error "leerer Text"
                               | p == [] = error "leeres Pattern"
                               | (length p) > (length o) = error "Pattern größer als Text"
                               | (t:ts) == [] = []
                               | (a:as) == [] = ((length(o)) - (length (t:ts))):(kmp p p (take (length p) (drop (length p) (t:ts))) (drop (length p) (t:ts)) o)
                               | (b:bs) == [] = []
                               | a == b = (kmp p as bs (t:ts) o)
                               | (head(drop ((length p) - (length (a:as))) (prefix p))) == 0 = (kmp p p (take (length p) ts) ts o)
                               | otherwise = (kmp p (drop (head(drop ((length p) - (length (a:as))) (prefix p))) p) (take (length p) (drop (head(drop ((length p) - (length (a:as))) (prefix p))) (t:ts))) (drop (head(drop ((length p) - (length (a:as))) (prefix p))) (t:ts))  o)

非常感谢!

3 个答案:

答案 0 :(得分:2)

使用-fwarn-incomplete-patterns-Wincomplete-patterns,GHC会告诉您需要添加哪些模式以避免此错误:

test.hs:5:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘hprefix’:
        Patterns not matched:
            [] [] _
            (_:_) [] _
  |
5 | hprefix [] (i:is) int = []
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^...

test.hs:17:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘kmp’:
        Patterns not matched:
            _ [] _ _ _
            _ (_:_) [] _ _
            _ (_:_) (_:_) [] _
   |
17 | kmp p (a:as) (b:bs) (t:ts) o | o == [] = error "leerer Text"
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

答案 1 :(得分:0)

你的遗失模式是之前守卫。 (a:as)之类的内容无法与[]匹配,即使您为此提供了警卫。你应该写得更像:

kmp _ _ _ _ []                          = error "leerer Text"
kmp [] _ _ _ _                          = error "leeres Pattern"
kmp p _ _ _ o | (length p) > (length o) = error "Pattern größer als Text"
kmp _ _ _ [] _                          = []
kmp _ _ _ [] _                          = []
kmp p [] _ t o                          = ((length o) - (length t))):(kmp p p (take (length p) (drop (length p) t)) (drop (length p) t) o)
kmp _ _ [] _ _                          = []
kmp p (a:as) (b:bs) t o | a == b        = (kmp p as bs t o)
kmp p (a:as) (b:bs) (t:ts) o | (head(drop ((length p) - (length (a:as))) (prefix p))) == 0 = (kmp p p (take (length p) ts) ts o)
kmp p a _ t o                           = (kmp p (drop (head(drop ((length p) - (length a)) (prefix p))) p) (take (length p) (drop (head(drop ((length p) - (length a)) (prefix p))) t)) (drop (head(drop ((length p) - (length a)) (prefix p))) t)  o)

虽然你应该考虑进一步打破这个问题。这真的很难理解。

答案 2 :(得分:0)

很明显,您的hprefixkmp功能并非全部,因此并非详尽无遗。

要了解原因,请回忆kmp的第一个(也是唯一的)等式:

kmp p (a:as) (b:bs) (t:ts) o = ...

在这里,您定义kmp强制第二,第三和第四个参数为非空字符串。因此,为了总计kmp,您必须覆盖这些丢失的案例,例如,将另一个等式添加到kmp的模式匹配定义中,该定义将捕获这些字符串为空的情况:

kmp p s1 s2 s3 o = ...

编译器只是声明如果在上面提到的地方用空字符串调用kmp,程序可能会在运行时崩溃,因为它没有定义。