考虑字符串
aabaabaabaabaab
显然,此字符串由aab
的5个相邻出现组成,因此我希望我的正则表达式匹配aab
。
详细说明:aabaab
不是可接受的输出,因为它是通过重复aab
而产生的。但是aab
是一个有效的结果,因为它不是由重复的较短字符串构成的。
出于问题的原因,我们假设重复段周围可能有其他文本(例如11aabaabaabaabaab22
或甚至xaabaabaabaabaabaa
)。因此,无法使用^
或$
锚定正则表达式。
失败的想法#1:(.+?)\1+
这会捕获aa
而不是预期的aab
。
失败的想法#2:(.+)\1+
这会捕获aabaab
。
纯正的正则表达式可以做到这一点吗?如果是,是否有可能没有动态宽度的后视?
答案 0 :(得分:5)
您可以使用两个前瞻,第一个搜索最长的模式,第二个搜索最小的模式。重复的第二图案必须(至少)在相同位置结束或在第一图案重复之后结束。要检查这一点,您必须在第一个前瞻中捕获字符串的结尾,并在第二个前瞻中使用对此捕获的反向引用。
(?=(.+)\1+(.*))(?=(.+?)\3+\2$)\3+
结果在第3组
也:
(?=(.+)\1+(.*))(.+?)\3+(?=\2$)\3*
请注意,这两个正则表达式模式为字符串中的一个位置提供结果。如果你想知道对于所有字符串重复一次的最长子字符串的最短模式是什么,你必须找到所有字符串并选择带代码的最长字符串。您可以使用模式来重叠结果:
(?=(.+)\1+(.*))(?=(.+?)\3+\2$)(?=(\3+))
(使用第4组)
答案 1 :(得分:1)
def largest_pattern(value)
/(.+)\1+/.match(value).try("[]", 1)
end
def smallest_pattern(value)
/^(.+?)\1+$/.match(value).try("[]", 1)
end
def largest_distinct_pattern(value)
val = largest_pattern(value)
if val
while(new_val = smallest_pattern(val))
val = new_val
end
val
else
nil
end
end
largest_distinct_pattern("aabaabaabaabaab")
=> "aab"