1

在我的 Lua 5.1 环境中可用的显然是默认的 Lua 模式匹配,但也是相当新的 PCRE 和 LPEG 版本。老实说,我不在乎使用哪一个。只要我的问题得到有效解决,我就很高兴。(我个人对 LPEG 的了解几乎不存在,但我听说它有一些非常好的品质。)

我有一个表,其中包含某些字符串模式作为键,一旦键匹配,将使用随附的值......这意味着它们对于这个问题并不重要。

假设你有:

tbl = { ["aaa"] = 12, ["aab"] = 452, ["aba"] = -2 }

现在我的目标是找出其中哪一个首先在特定字符串中匹配,例如"accaccaacaadacaabacdaaba".

实际上,键更多,匹配字符串更长。这意味着简单地逐一匹配所有键并比较匹配开始的列是一种非常低效的解决方案,对我来说不可行。

部分匹配字符串也可以有相当多的重叠。从理论上讲,我知道每个键模式一个状态机在这方面是理想的;只需完成每个模式的动作,当你完全匹配其中一个模式时,你就完成了。

但是当我的环境中有这么多模式匹配库时,我自己去编写类似的代码会很疯狂。我知道唯一有技术能力的是PCRE。只需附加诸如之类的键"aaa|aab|aba",您将获得第一个可行的匹配项。

但也有问题。一方面,我不确定在编译这样的匹配时它有多智能。(我认为它首先尝试'aaa',一旦失败就完全放松,然后完全尝试aab,但我没有测试过)与匹配它相比,它不会太有效,"a(a[ab]|ba)"因为相似性得到更快解决。

此外,我希望能够提供一些灵活性(“a.ad”,其中第二个字符无关紧要,或者匹配一个数字......类似的基本内容)。在这种加法方法中使用这样的模式,我看不到有办法重新获得匹配的原始模式,因此我可以使用它附带的值。

(最坏的情况,我可以在表中生成很多条目来匹配每个可能的通配符变化并取消模式要求,但老实说我不想这样做。)

哪个库是完成这项工作的正确工具,以及如何在不重新发明轮子的情况下最好地使用所述库来实现上述目标?

4

2 回答 2

0

对您的问题的评论提到了 Aho-Corasick 算法。

如果您的环境可以访问os.executeor io.popen,您可以调用fgrep -o -f patterns filename,其中patterns是包含用换行符分隔的模式的文件的名称,而 filename 是您的输入的名称。-o表示只输出匹配项,每行一个。您可以替换filename为,-以便fgrep从标准输入中读取:echo "String to match" | fgrep -o -f patterns.

fgrep实现 Aho-Corasick 算法。

但是,请记住 Aho-Corasick 算法不能识别元字符。

于 2020-09-22T01:10:29.950 回答
0

正如 Alexander Mashin 的回答所说,Aho-Corasick 算法是一种有效的算法,可以解决您的问题。在 Lua 领域,cloudflare / lua-aho-corasick是使用 FFI 的 LuaJIT 实现。还有一个纯 lua 实现jgrahamc/aho-corasick-lua可能会更慢。

于 2021-10-25T03:16:00.570 回答