WildCard字符串比较(空或所有字符)

时间:2016-01-31 19:05:31

标签: c++ string compare wildcard

我试着在C ++中编写一个函数来比较两个字符串s1和s2,其中只有s2有'?'字符。  '?'字符代表匹配任何角色的能力, 包括空字符。例如,colo?r匹配“颜色”和“颜色”。 这个 查询应报告匹配的每个单词。其他例子:

您好:hello__True

你好:h?l?o - true(两者都充当通配符)

hllo:h?l?o - true(首先?作为空,第二个?充当通配符)

hlo:h ?? lo - true(两者都是空的)

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

你好:h ??? p - false(p确实匹配任何可能的字符选项)

我尝试使用循环使用很多函数,但我只能处理所有'?'的问题作为空或通配符。当一个人作为空行为而另一行作为通配符时,那么有许多不同的字符串可供比较,事情就会失控。

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

1 个答案:

答案 0 :(得分:0)

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

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

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

  1. ?应匹配一个字符(为了匹配完整的模式),所以只需使用输入中的下一个字符然后继续。
  2. ?不应与字符匹配,在这种情况下,您将继续使用模式中的下一个字符并保持输入字符串不变。
  3. 当然,您无法知道在何时选择这些案例。因此,您需要能够回到那一点,以防您的猜测错误。

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

    您只需先使用剩余模式和输入字符串调用匹配函数,如果失败,则使用剩余模式和输入字符串调用匹配函数,而不使用其第一个字符(从而使?消耗一个角色。)

    示例:

    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次调用,只留下一次必要的递归)。