用于检测周期性字符串的正则表达式

时间:2016-07-12 07:51:57

标签: regex

  

字符串p的句点w是任意正整数pw[i]=w[i+p]   每当定义这个等式的两边时。让per(w)表示   最小句点w的大小。我们说字符串w是   周期性iff per(w) <= |w|/2

非正式地,周期性字符串只是一个由重复至少两次的前缀组成的字符串。唯一的复杂因素是,在字符串的末尾,我们不需要前缀的完整副本。

例如,考虑字符串x = abcabper(abcab) = 3x[1] = x[1+3] = ax[2]=x[2+3] = b并且没有较小的期限。因此字符串abcab不是周期性的。但是,字符串ababa定期为per(ababa) = 2

作为更多示例,abcabcaababababaabcabcabc也是定期的。

  

是否有正则表达式来确定字符串是否是周期性的?

我真的不介意正则表达式的哪种风格,但如果它有所作为,那么Python re支持的任何内容。

3 个答案:

答案 0 :(得分:5)

您需要的是反向引用

\b(\w*)(\w+\1)\2+\b

这甚至与abcabcaababababa匹配。

请注意,作为反向引用的机制(在这种情况下是必要的)使表达式属于常规语法。

答案 1 :(得分:4)

您可以使用Regex反向引用。

例如(.+)\1+。此模式将匹配由至少一个字符()组成的组.+。该组\1(后退参考)必须至少重复一次才能进行比赛。

字符串ababa匹配,并找到ab作为第一组。

字符串abcab不匹配。

稍后修改

如果您想要重复至少两次的前缀,可以将模式更改为:^(.+)\1+。问题是我认为你不能将字符串的结尾与前缀的子字符串匹配。因此,任何以重复模式开头的字符串都会匹配,但它会忽略字符串的结尾。

以后编辑

受到@tobias_k回答的启发,我就是这样做的^((.+)(?:.*))\1+\2?$。它查找具有前缀的字符串(它查找它可以找到的最长前缀),该字符串重复至少两次,结尾必须是前缀的起始部分。

匹配中的第一个捕获组将是重复的前缀。

https://regex101.com/r/jQ3yY1/2

如果您想要重复的最短前缀,可以使用此模式^((.+?)(?:.*?))\1+\2?$

答案 2 :(得分:4)

您可以使用^(.+)(.*)(\1\2)+\1?$等正则表达式。

  • ^...$从字符串的开头到结尾
  • (.+)一段时间内始终重复(例如a中的ababa
  • (.*)句号的可选部分,在结尾处重复(例如b中的ababa
  • (\1\2)+整个时期的一次或多次重复
  • \1?期间第一部分的可选最终重复

在Python中:

>>> p = r"^(.+)(.*)(\1\2)+\1?$"
>>> re.match(p, "abcab")
None
>>> re.match(p, "abcabca")
<_sre.SRE_Match at 0x7f5fde6e51f8>

请注意,这与空字符串""不匹配,但也可以认为是周期性的。如果应匹配空字符串,则必须单独处理,例如只需在正则表达式的末尾附加|^$即可。