具有正则表达式模式regexPattern
,如何确定与regexPattern
匹配的最长字符串的长度。
虚构的int LongestLength(string pattern)
应该像这样工作:
Assert.Equals(LongestLength("[abc]"), 1);
Assert.Equals(LongestLength("(a|b)c?"), 2);
Assert.Equals(LongestLength("d*"), int.MaxValue); // Or throws NoLongestLengthException
虽然问题出在C#中,但C#和JavaScript的答案都很好。
答案 0 :(得分:4)
proper regex使用运算符?
,*
和+
以及|
加上括号,字符类,非常简单明了当然还有普通人物。实际上,甚至\1
式的反向引用(它们不是正则表达式的正式定义的一部分,并且使关于正则表达式的一些问题复杂化)可以毫无问题地处理。
正则表达式只是树结构的紧凑编码(类似于数学公式是描述算术的树结构的紧凑编码)。在每对相邻的字符之间有一个隐含的" follow"对应于具有2个子节点的节点的运算符,一个是左边的子规则,另一个是正则表达式的其余部分;由|
个字符分隔的子序列序列对应于单个" alt"具有尽可能多的子节点的节点(即,比|
个字符的数量多一个),而每个其他运算符只有一个子节点(即它操作的子节点),以及每个普通字符或字符上课没有孩子。要计算最大长度匹配字符串,您可以直接遍历此树结构,在每个节点贪婪地分配与该节点匹配的最长字符串的长度,同时了解与其匹配的最长字符串孩子。
决定与此树中任何给定节点匹配的最长字符串长度的规则是:
xy
):maxlen(x)+ maxlen(y)a|b|...|z
):max(maxlen(a),maxlen(b),...,maxlen(z))x?
):maxlen(x)x*
)或posrep(x)(x+
):infinity [...]
):1 \1
- 样式反向引用:相应带括号的表达式的maxlen 一个结果是*
或+
存在于任何地方(除非转义或明显是字符类的一部分)将导致无穷大向上传播直到它到达根目录。
Regex: abcd
"Function call syntax": follows(a, follows(b, follows(c, d)))
As a tree:
follows
/ \
a follows
/ \
b follows
/ \
c d
第二个例子:
Regex: (a|b|de)c?
"Function call" syntax: follows(alt(a, b, follows(d, e)), maybe(c))
As a tree:
follows
/ \
alt maybe
/ | \ \
a b follows c
/ \
d e
对于第二个正则表达式/树,自下而上遍历将为叶节点a,b,d,e和c分配maxlen为1;然后底部的maxlen跟随()节点是1 + 1 = 2;那么alt()节点的maxlen是max(1,1,2)= 2;可能节点的maxlen为1;最顶层的maxlen跟随()节点,因此对于整个正则表达式,是2 + 1 = 3.
如果你的意思是允许其他Perl风格增强功能的正则表达式,它可能会变得复杂得多,因为局部最佳长度选择可能会导致全局不理想。 (我原本以为Perl风格的扩展甚至可能使正则表达式图灵完成,这意味着通常无法确定是否存在任何匹配的字符串 - 但是{{3}似乎表明情况并非如此,除非您在?{...}
构造中允许。)
答案 1 :(得分:0)
因此,我将如何执行此功能首先创建键值对数据类型。然后用每种类型的正则表达式语法填充数据类型。所以关键是正则表达式语法(例如:“*”)。该值将增加到匹配的字符串的可能长度。所以关键:“*”的值为int.maxvalue。因此,您将遍历列表并搜索为任何语法传入的正则表达式,并总结您找到的所有值并将其返回。但是,您必须记住一些语法被转义,因此您无法计算它们。除了一些语法自动使可能的长度为int.maxvalue(“*”,“+”等等)。因此,请首先检查这些语法,以便在找到这些类型的正则表达式语法后立即自动发回int.maxvalue。