通配符匹配反向查找

时间:2018-09-16 10:13:36

标签: regex wildcard matching

我有一个模式列表,这些模式的体内任何位置都包含零个或多个通配符(*):

bleurgh
p0*
p*w
p*w*
*01
*.nowsich.* (dots here are meaningless)

仅允许使用通配符(这不是任何形式的完整正则表达式),并且它们可以出现在模式中的任何位置。不允许使用仅使用通配符的模式,并且双通配符(**)是荒谬的,因为它与*相同(但可以保证有人会尝试。)大约有100,000个一百万。

代码将看到可能匹配的新目标字符串:

p01w01
pod01whiskey02
ppp.nowsich.com
aZL8u4qXfg!LooksLikeRandomGarbageToMe!kx961giRVV
callmeishmael

这些字符串是无界的,但可能少于32个字符,并且代码将以每秒两次的顺序看到它们(这是一种低速率的东西。)

我正在寻找一种方法来反向查找字符串可能匹配的模式:(这里是输入到输出)

m01z01 -> *01
p03w01 -> p0*, p*w*, *01
bleurgh -> bleurgh
www.nowsich.org -> *.nowsich.*
wut -> [the empty list]

我没有受到记忆的束缚;更快的查找肯定更好。

到目前为止,我能想到的最好的办法是建立模式组件的有向图,其中每个组件都是split("*", pattern)的输出,尾随的通配符绑定到它们的叶子:

        ___   {implied root node} 
       /      /    |           \
[bleurgh]  [p0]   [p]          [] // leading wildcard?
           /      /           /  \
         [w]    [w*]       [01]  [.nowsich.*]

...并在树上执行DFS,选择那些根节点正则表达式与从子树的父节点重新编译的模式(一直到根)相匹配的子树。我不喜欢这样的想法, O(log n)?正则表达式,但数据集并不庞大。另外,我相信我必须始终搜索树的“前导通配符”分支,因此也许可以搜索一对这样的树(有无前导通配符的一棵树)。

有些先前的艺术似乎由于各种原因而没有应用:

Good algorithm and data structure for looking up words with missing letters?

Efficient string matching algorithm

这两个都有其自己的约束,这些约束与我的不相称。

问题是:a)我上面概述的方法是否有意义;和b)您有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

完成了一些实际的写作,这就是我学到的东西:

  • 这个想法确实可行,但是不要使用树,而是使用trie。在针对模式测试字符串时,它将使您跳过没有值且只有一个子节点的节点,这减少了您需要执行的正则表达式的数量。
  • 跟踪和前导通配符至少在我的情况下需要特殊对待(请记住,在我的情况下,只有通配符-*-char具有特殊含义。)如果没有前导或尾随通配符,则需要在模式的第一个或最后一个键上包含锚点。这意味着模式*p0*p0*由树中的两个节点表示。 (对于叶节点类似-即模式中的最终令牌。)
  • 针对我的情况的另一条注释:我需要转义对正则表达式有意义但对我无意义的所有内容,例如,字符.[],{{1 }},{等。可以将它们包括在模式匹配树中,但您必须以不同的方式标记化标记。
  • 存储与之匹配的已编译正则表达式可以提高速度。就我而言,这是用Go语言编写的,因此我可以为树中的每个节点存储}的结果。