【发布时间】:2012-06-11 19:50:17
【问题描述】:
我正在学习自动机。你能帮我理解一下带 Kleene 闭包的自动机是如何工作的吗?假设我有字母 a、b、c,我需要找到以 Kleene 星号结尾的文本 - 比如 ab*bac - 它是如何工作的?
【问题讨论】:
标签: algorithm kleene-star
我正在学习自动机。你能帮我理解一下带 Kleene 闭包的自动机是如何工作的吗?假设我有字母 a、b、c,我需要找到以 Kleene 星号结尾的文本 - 比如 ab*bac - 它是如何工作的?
【问题讨论】:
标签: algorithm kleene-star
这个问题似乎更多的是关于自动机如何处理 Kleene 闭包,而不是 Kleene 闭包的含义。
使用简单的正则表达式,例如abc,设计一个自动机来识别它是非常简单的。每个状态基本上都会告诉您到目前为止您在表达式中的位置。状态 0 意味着它还没有看到任何东西。状态 1 表示已看到 a。状态 2 表示已看到 ab。等等。
Kleene 闭包的困难在于像ab*bc 这样的模式会引入歧义。一旦自动机看到a,然后面对b,它不知道b是b*的一部分还是跟在它后面的文字b,它不会在它读取更多符号之前不知道——也许更多。
简单的答案是自动机只是有一个状态,字面意思是它还不知道选择了哪条路径。
在简单的情况下,您可以直接构建此自动机。在一般情况下,您通常会构建一种称为非确定性有限自动机的东西。您可以模拟 NDFA,或者 - 如果性能很关键 - 您可以应用一种将 NDFA 转换为确定性算法的算法。该算法本质上会为您生成所有模棱两可的状态。
【讨论】:
ab*bc = ab+c。这实际上意味着“a,至少一个 b,c”。对不起,我没有发现任何模棱两可的地方。在自动机看到a 之后,它只是在寻找至少一个b,然后是c。一旦自动机处于状态ab+,它会在收到bs 时保持在那里。自动机只能走一条路。
b 是b* 还是b 的一部分。所以你需要一种状态来应对这种模糊性。
Kleene 星号('*') 表示您可以根据需要(0 或更多)出现任意数量的字符。
a* 将匹配任意数量的 a。
(ab)* 将匹配任意数量的字符串“ab”
如果您尝试匹配表达式中的实际星号,您编写它的方式完全取决于您正在使用的正则表达式的语法。对于一般情况,反斜杠\ 用作转义字符:
\* 将匹配一个星号。
要在结尾识别模式,请使用连接:
(a U b)*c* 将匹配任何结尾包含 0 个或多个 'c',前面有任意数量的 a's 或 b's 的字符串。
对于以 Kleene 星号结尾的匹配文本,同样,字符串可以出现 0 次或多次:
ab(c)* - 可能的匹配项:ab、abc、abcc、abccc 等。
a(bc)* - 可能的匹配项:a、abc、abcbc、abcbcbc 等。
【讨论】:
(a U b)*c* 将匹配任何末尾包含 0 个或多个 'c',前面有任意数量的 a's 或 b's 的字符串。
a*(a U b U c)
你的英语表达 ab*bac 应该是这样的:
a 后跟 0 个或多个 b 后跟 bac
strings that would evaluate as a match to the regular expression if used for search
abac
abbbbbbbbbbac
abbac
strings that would not match
abaca //added extra literal
bac //missing leading a
如上一个答案所述,实际搜索 * 需要一个转义字符,该字符是特定于实现的,并且需要了解您选择的语言/库。
【讨论】: