【问题标题】:WildCard string Compare (Empty or All character)通配符字符串比较(空或全字符)
【发布时间】:2016-05-09 04:02:35
【问题描述】:

我试图用 C++ 编写一个函数,它可以比较两个字符串 s1 和 s2,其中只有 s2 有 '?'人物。 ‘?’ 字符代表匹配任何字符的能力, 包括空字符。例如, color?r 同时匹配“color”和“color”。 这 查询应报告匹配的每个单词。其他例子:

你好:你好__True

hello:h?l?o--true(都 ? 充当通配符)

hllo:h?l?o--true(第一个 ? 为空,第二个 ? 为通配符)

hlo:h??lo--true(都 ? 充当空)

你好:h?lo--false(?字符只能替换一个字符,不能替换字符串)

hello:h???p--false(p 匹配任何可能的字符选项)

我尝试使用循环使用很多函数,但我只能处理所有“?”的问题充当空或通配符。当一个作为空而另一个作为通配符时,有太多不同的字符串需要比较,事情就会失控。

我的教授告诉我递归是解决这个问题的关键,但是我们还没有讨论太多关于递归的内容。 请帮助我提供一些可以使用回溯技术解决此问题的建议/代码。

【问题讨论】:

    标签: c++ string compare wildcard


    【解决方案1】:

    基本上,您使用通配符遍历字符串(从现在开始我将调用该字符串 pattern):

    如果模式的第一个字符不是?,则尝试从输入字符串(另一个没有通配符的字符串)中准确使用该字符。

    如果模式的第一个字符是?,那么你有两种情况:

    1. ? 应该匹配一个字符(为了匹配完整的模式),所以只需使用输入中的下一个字符并继续。
    2. ? 不应匹配字符,在这种情况下,您将继续使用模式中的下一个字符并保持输入字符串不变。

    当然,您之前无法知道何时选择这些案例中的哪一个。所以你需要能够回到那个点,以防你的猜测是错误的。

    为此,您可以使用递归(或更准确地说:就局部变量等而言,您从递归调用中获得的新上下文):

    您只需首先使用剩余的模式和输入字符串调用匹配函数,如果失败,您使用剩余的模式和输入字符串调用匹配函数没有它的第一个字符(从而使? 消耗一个字符)。

    例子:

    pattern: s?y
    input:   say
    

    模式的第一个字符是s,这是正常的非通配符匹配,所以查看匹配的输入的第一个字符,继续前进:

    pattern: ?y
    input:   ay
    

    现在有一个通配符要匹配,所以假装它没有消耗任何字符,让我们看看它会把我们带到哪里。调用匹配函数:

    pattern: y
    input:   ay
    

    哎呀,这不匹配(a != y),所以此时返回false。这让我们回到了我们调用匹配函数的地方(在上面的步骤中),给我们留下了:

    pattern: ?y
    input:   ay
    

    我们已经尝试将通配符匹配为无字符,现在尝试将其匹配为任何字符,从而消耗a

    pattern: y
    input:   y
    

    哇,匹配,下一次运行时两个字符串都是空的,所以我们有一个匹配!


    这似乎是家庭作业,您可能必须在 C++ 中实现。我不会给你那个代码。相反,我会给你一个不同语言的实现——Clojure——它应该能让你进一步理解上述算法。

    (ns wildcards
      (:refer-clojure))
    
    (defn- dpr
      "Debug printing with poor man's indendation"
      [pattern & rest]
      (print (repeat (- 6 (count pattern)) " "))
      (apply println rest))
    
    (defn wildcard-match [input pattern]
      (println "wildcard-match " input pattern)
      (if (or (empty? input) (empty? pattern))
        ;; One is empty, return true if both are
        (and (empty? input) (empty? pattern))
        ;; Else
        (if (= (first pattern) \?)
          ;; Wildcard, so with short ciruiting or:
          (or (do
                (dpr pattern "Try to match no character...")
                (wildcard-match input (rest pattern)))
              (do
                (dpr pattern "Ok, so try to match any character...")
                (recur (rest input) (rest pattern))))
          ;; Non-Wildcard, test for equality, and if equal, go on.
          (and (= (first pattern) (first input))
               (recur (rest input) (rest pattern))))))
    
    
    
    (defn testcase [input pattern]
      (println "#####################################")
      (println "Trying to match" input "with" pattern)
      (println "=>" (wildcard-match (seq input) (seq pattern)))
      (println))
    
    
    (doall (map #(testcase (first %) (second %))
      [["hello" "hello"]
       ["hello" "h?l?o"]
       ["hllo" "h?l?o"]
       ["hlo" "h??lo"]
       ["hello" "h?lo"]
       ["hello" "h???p"]]))
    

    你可以看到这里正在执行: http://ideone.com/8o4QdR

    由于 Clojure 是一种使用递归的函数式语言,因此您会看到很多递归发生在那里。将其转换为更命令式的语言(如 C++)应该可以消除大部分递归,尤其是那些可以被循环替换的递归(这就是所有 recur 调用,只留下一个必要的递归使用)。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多