类似的正则表达式为最大连续子串计数返回不同的答案

Similar regexes returning different answers for maximum consecutive substring count

我正在使用正则表达式查找给定字符串中子字符串的最大连续重复次数。在下面的示例中,有 9 个连续的 AAGAA 子字符串。第一种方法 returns 连续子串的所有不同段的长度,第二种方法 returns 整体最大值。因此,max(lens) 应该等于 val. 但是,在使用 val 的方法中,有一个包含 10 次重复 AAGAA 的匹配项,即使原始字符串最多包含只有 9.

我花了很多时间查看正则表达式教程和 regex101.com 但我无法弄明白。 "(?=((" + re.escape(substring) + ")+))" 在哪里找到额外的子串?

string='AAGAAAAAAAAGAAAGAAAAGAAAAGAAAAGAAAAGAAAAGAAAAGAAAAGAAAAGAAAAGAA'
substring = 'AAGAA'

#this one is right; returns [1,1,9], as desired
sl = len(substring)    
regex = re.compile(f'((?:{substring})+)')    
lens = [len(m) // sl for m in regex.findall(string)]

#this one is wrong; returns 10, should return 9
pattern = re.compile("(?=((" + re.escape(substring) + ")+))")
matches = re.findall( pattern, string )
val = max(len(m[0]) // len(substring) for m in matches)

您看到额外子字符串的原因是因为您使用的正则表达式会找到重叠匹配项(有关解释,请参阅 this question,但本质上它找到重叠匹配项的原因是因为正则表达式仅包含先行;这不会消耗任何字符),因此它允许正则表达式不仅匹配从 string[9] 开始的单次出现的 AAGAA,而且还匹配从 [=12= 开始的 10 次出现的序列].由于后一个匹配与前一个匹配部分重叠,因此它不会与您的第一个正则表达式匹配(它实际上在匹配时消耗字符)。第一个正则表达式匹配从 string[18] 开始的 9 次出现的序列,而不是因为匹配了 string[9] 处的单次出现,它寻找匹配的下一个位置是 string[14],此时它已超过 10 次比赛开始时间。