我正在尝试创建一个正则表达式,在这个正则表达式中,我们可以检查某个引用集中的所有字母是否都存在于其他字符串中,但只能是奇数(1、3、5,…)。在
以下是代表问题的DFA的(非常)粗略的图像:
我开始使用一个有限集{a, b}
,因此我基本上要检查“字符串中是否同时存在a
s的奇数和{
不幸的是,我自己没有走多远。我第一次读到了this thread,它与这个概念非常相似,但是无法从{
这是我目前为止的想法:^((ab|ba)(bb|aa)?|(bb|aa)?(ab|ba))+$
。这基本上检查是否存在ab
或ba
后跟bb
或{ab
,ba
,abaa
,abbb
,baaa
,或{bbaa
,我似乎无法调整它以匹配字符串bbaaba
。在
另外,上面的方法不能动态调整以考虑{a, b, c}
,尽管我愿意放弃这个来解决初始问题。在
下面是我的测试字符串和所需的输出,括号中有原因:
"ba" # True (1a, 1b)
"abbb" # True (1a, 3b)
"bbba" # True (1a, 3b)
"bbab" # True (1a, 3b)
"ababab" # True (3a, 3b)
"bbaaba" # True (3a, 3b)
"abb" # False (2b)
"aabb" # False (2a, 2b)
"aabba" # False (2b)
"" # False (0a, 0b is "even")
"a" # False (0b is "even")
"b" # False (0a is "even")
那么,通过regex实现这一点吗?或者正则表达式比DFA更有限吗?我知道这可以通过一个基本的循环来完成,但这不是我要做的。在
正则表达式的限制不超过DFA;事实上,它们是等价的。(带有反向引用的Perl风格的“regex”更强大,因此它们根本不是“常规的”
如果字符串只包含
a
s,我们可以轻松地编写regex:如果其他字母也可能出现在中间,我们仍然可以忽略这些字符:
^{pr2}$因为regex相当于DFA,所以每个字母都有一个DFA。其实很简单:
State(0)是开始状态(“偶数个
a
出现”),State((1))是唯一接受的状态(“奇数个a
s可见”)。如果我们看到一个a
,我们将进入另一个状态;对于任何其他字符,我们将保持相同的状态。在现在DFA的好处是它们是可组合的。特别是在交叉口处是封闭的。这意味着,如果我们有一个能够识别语言“包含奇数个
a
s”的DFA和识别语言“包含奇数b
s的字符串”的DFA,我们可以将它们组合成一个能识别这两种语言交集的DFA,也就是说,“包含奇数a
和奇数b
的字符串”。在我不想详细介绍这个算法,但是this question有一些很好的答案。得到的DFA将有四种状态:“偶数个
a
s可见,偶数b
s已见”,“偶数a
s可见,奇数b
s可见”,等等。在而且因为dfa等同于regex,所以也存在一个与这些字符串精确匹配的regex。同样,我不会详细介绍算法,但是here is an article可以很好地解释它。为了方便起见,它还附带了一些Python 3代码来完成这些肮脏的工作:
库中可能有一个bug,或者我用错了,因为开头的
a*
不可能是正确的。但是你得到了一个想法:虽然理论上是可能的,你真的不想为此使用regex!是的:
说明:
^{pr2}$正则表达式本身不匹配任何字符,因此您将始终获得一个空字符串作为匹配结果(这与将
None
作为匹配结果不同):这里有一种方法,使用lookaheads依次断言每个条件。在
下面是a demo和您的示例。(演示中的
\n
用于演示目的。另外,如果只需要测试匹配,而不是捕获,则可以删除(.*)$
。)我将很快添加一个解释。在
说明
我们只需要看一半:
^{pr2}$相关问题 更多 >
编程相关推荐