8

我有一个场景,我想在已经有通配符的字符串上使用通配符模式进行搜索。用我的话来说,我会说这是一种 2 路模式匹配要求。

输入和模式字符串可以具有以下通配符之一/两者 - ?表示单个字符,% 表示零个或多个字符。假设这些是输入和模式字符串中唯一允许的 2 个通配符。

例如:

bool IsMatch(string input, string pattern) //如果输入字符串与模式匹配则返回True,否则返回False。

IsMatch("XYZ%", "?Y%") // 应该返回 True

IsMatch("YY?", "?Y%") // 应该返回 True - 输入字符串中的最后一个字符需要一个字符,因为模式匹配 Y 之后的零个或多个字符(这意味着它包括单个字符匹配出色地)

IsMatch("X123", "?Y%") // 应该返回 False - 模式期望的输入字符串中缺少 Y

IsMatch("?Y%", "?Y%")// 应该返回 True

IsMatch("%", "?Y%")// 应该返回 True - 输入字符串有一个通配符 % 表示零个或多个字符,也可以有任何字符。在某种程度上,它本身就是一种模式,代表任何大小的任何东西。

我能够找到仅谈论对非通配符字符串执行通配符模式匹配的文章(例如:Regex)。我正在寻找关于算法的指针/想法,因为当我开始放下它时,我很难想出一种可以进行这种匹配的算法。感谢您的投入。

4

1 回答 1

2

正如我在对最一般情况的评论中所写的那样,您必须创建两个表达式的最小确定性有限自动机并比较这两个自动机。话虽如此,您的问题可能有一个蛮力/穷人的解决方案。

根据您的示例,您似乎有兴趣查看输入/模式之一是否与另一个生成的所有字符串匹配。

IsMatch("XYZ%", "?Y%") // returns true because ?Y% matches a superset of strings matched by "XYZ%"
IsMatch("%", "?Y%") // returns true because "%" matches a superset of "?Y%"

您可以检查是否input 确实匹配生成的字符串子集,pattern只要

  • 你真的可以把自己限制在 % 和 ? 指定的运算符
  • 您的输入/模式字符串相当短 - 更具体地说,输入或模式中 % 的出现少于大约 20 次左右。

基本思想是您生成一个代表字符串列表,input并使用您最喜欢的正则表达式引擎将每个字符串与模式匹配。如果所有代表都匹配 -input匹配 的子集pattern。该算法IsSubset可描述如下

let c = some character not in `pattern` (lexically speaking)
let searchString = replace all occurences of '?' in input with c
add searchString to setOfSearchStrings
foreach occurence of '%' in input
    foreach str in setOfSearchStrings
        replace str with two strings - {str with c in place of '%', str without the '%'}

foreach str in setOfSearchStrings
   if str doesn't "regex" match with pattern 
       return false

return true

例如,如果输入是 ?X%YZ% 并且pattern不包含字符 A 生成的列表将是
AXYZ
AXYZA
AXAYZ
AXAYZA

很容易看出,此列表中的字符串数为 2^n,其中 n 是输入中 '%' 的数量。

此外,交换参数的顺序并反过来找出关系也很容易。所以实际上你的

IsMatch(input,pattern) = IsSubset(input,pattern) || IsSubset(pattern,input)
于 2013-11-08T07:19:41.567 回答