对于正则表达式模式,如何确定与模式匹配的最长字符串的长度
本文关键字:模式匹配 字符串 何确定 正则表达式 模式 | 更新日期: 2023-09-27 18:00:39
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 的答案都很好。
对于一个正确的正则表达式来说,这非常简单,只使用运算符?
、*
、+
和|
,加上括号、字符类,当然还有普通字符。 事实上,即使是'1
式反向引用(这不是正则表达式正式定义的一部分,并且确实使有关正则表达式的一些问题复杂化(也可以毫无问题地处理。
(类似于数学公式是描述算术的树结构的紧凑编码(。 在每对相邻字符之间都有一个隐式的"跟随"运算符,它对应于一个具有 2 个子节点的节点,一个是其左侧的子正则表达式,另一个是正则表达式的整个其余部分;由|
个字符分隔的子正则表达式序列对应于单个"alt"节点,该节点具有与替代项一样多的子节点(即,比|
字符的数量多一个(,而其他每个运算符只有一个子项(即它操作的子正则表达式(,并且每个普通字符或字符类根本没有子项。 要计算最大长度匹配字符串,您只需对此树结构进行自下而上的遍历,在每个节点上贪婪地分配与该节点匹配的最长字符串的长度,给定与其子节点匹配的最长字符串的知识。
用于确定与此树中任何给定节点匹配的最长字符串长度的规则如下:
- follow(x, y( (
xy
(: maxlen(x( + maxlen(y(
alt(a, b, ..., z( ( - b(, ..., maxlen(z((
- 也许(x( (
x?
(: 麦克斯伦(x( - rep(x( (
x*
( 或 posrep(x( (x+
(: 无穷大 - 任何其他单个字符或字符类 (
[...]
(: 1 -
'1
样式反向引用:对应括号表达式的 maxlen
a|b|...|z
(: max(maxlen(a(, 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;然后底部 follows(( 节点的 maxlen 为 1 + 1 = 2; 则 alt(( 节点的 maxlen 为 max(1, 1, 2( = 2; 可能节点的 maxlen 是 1; 最顶层的 follow(( 节点的 maxlen, 因此,对于整个正则表达式,是 2 + 1 = 3。
如果你的意思是允许其他 Perl 风格的增强功能的正则表达式,它可能会变得更加复杂,因为局部最优的长度选择可能会导致全局次优的长度选择。 (我曾认为 Perl 风格的扩展甚至有可能使正则表达式图灵完整,这意味着通常不可能确定是否有任何匹配的字符串 - 但这里的讨论似乎表明情况并非如此,除非您当然允许在?{...}
结构中。
所以我如何做这个函数是首先创建键值对数据类型。然后用每种类型的正则表达式语法填充数据类型。所以键将是正则表达式语法(例如:"*"(。该值将是它将增加多少匹配的字符串的可能长度。因此,键:"*"的值为 int.maxvalue。因此,您将遍历列表并搜索传入的任何语法的正则表达式,并将找到的所有值相加并返回。但是,您必须记住,某些语法是转义的,因此您无法计算它们。以及一些语法自动使可能的长度为 int.maxvalue("*"、"+"等(。因此,请先检查这些语法,以便在找到这些类型的正则表达式语法之一后立即自动发回 int.maxvalue。