【问题标题】:Find index of substring in another string Haskell在另一个字符串 Haskell 中查找子字符串的索引
【发布时间】:2021-09-15 10:46:52
【问题描述】:

我要创建一个带有两个参数(字符串)的函数。该函数应查看第一个参数是否是第二个参数的子字符串。如果是这种情况,它将返回每个出现的元组,其中包含子字符串的开始索引和子字符串结束的索引。 例如:

f :: String -> String -> [(Int,Int)]
f "oo" "foobar" = [(1,2)]
f "oo" "fooboor" = [(1,2),(4,5)]
f "ooo" "fooobar" = [(1,3)]

我们不允许导入任何东西,但我有一个 isPrefix 函数。它检查第一个参数是否是第二个参数的前缀。

isPrefix :: Eq a => [a] -> [a] -> Bool 
isPrefix [] _ = True
isPrefix _ [] = False
isPrefix (x:xs) (y:ys) |x== y = isPrefix xs ys
                       |otherwise = False

我在想一个解决方案可能是先在 x 上运行函数“isPrefix”,如果它返回 False,我在尾部 (xs) 上运行它,依此类推。但是,我正在努力实现它并努力理解如何返回字符串的索引(如果存在)。也许使用“!!”?你认为我在做某事吗?因为我是 Haskell 的新手,所以语法有点困难:)

【问题讨论】:

  • 不要使用!!。相反,通过递归第二个字符串继续。如果f "oo" "foobar"[(1,2)],如何更改该列表以获得f "oo" "ofoobar" 的正确结果? f "oo" "oofoobar" 呢?考虑如何重新使用尾部的结果,以便获得一个字符长的字符串的结果。使用mapisPrefix 可能会有所帮助。

标签: haskell


【解决方案1】:

我们可以创建一个函数来检查第一个列表是否是第二个列表的前缀。如果是这种情况,我们将 (0, length firstlist - 1) 添加到递归调用之前,我们将两个索引都加一。

这意味着这样的函数看起来像:

f :: Eq a => [a] -> [a] -> [(Int, Int)]
f needle = go
  where go [] = []
        go haystack@(_: xs)
            | isPrefix needle haystack = (…, …) : tl  -- (1)
            | otherwise = tl
          where tl = … (go xs)                        -- (2)
        n = length needle

因此,此处 (1) 将(…, …) 添加到列表中;对于 (2) tl 进行递归调用,需要通过将 2 元组的两项都加一来对列表进行后处理。

有一种更有效的算法可以做到这一点,您可以在递归调用中传递当前索引,或者您可以实现Knuth-Morris-Pratt algorithm [wiki],我将这些留作练习。

【讨论】:

    猜你喜欢
    • 2022-06-17
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    相关资源
    最近更新 更多