最大周期子串的正则表达式

时间:2016-07-12 10:37:24

标签: regex

这是A regex to detect periodic strings的后续行动。

  

字符串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也是定期的。

@horcruz等人给出了一个非常好的正则表达式来识别周期性字符串。它是

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

我想在更长的字符串中找到所有最大周期性子字符串。这些在文献中有时被称为 run

  

正式子字符串w是最大周期性子字符串,如果它是周期性的,既不是w[i-1] = w[i-1+p]也不是w[j+1] = w[j+1-p]。非正式地,&#34;运行&#34;不能包含在更大的&#34; run&#34;   在同一时期。

  • 字符串T = atattatt的四个最大周期性子串(运行)为T[4,5] = ttT[7,8] = ttT[1,4] = atatT[2,8] = tattatt

  • 字符串T = aabaabaaaacaacac包含以下7个最大周期性子串(运行): T[1,2] = aaT[4,5] = aaT[7,10] = aaaaT[12,13] = aaT[13,16] = acacT[1,8] = aabaabaaT[9,15] = aacaaca

  • 字符串T = atatbatatb包含以下三个运行。他们是: T[1, 4] = atatT[6, 9] = atatT[1, 10] = atatbatatb

  

是否有正则表达式(带反向引用)将捕获所有最大值   周期性子串?

我真的不介意正则表达式的哪种风格,但如果它有所作为,那么Python模块re支持的任何内容。但是,如果这样可以解决问题,我甚至会对PCRE感到满意。

(此问题部分复制自https://codegolf.stackexchange.com/questions/84592/compute-the-maximum-number-of-runs-possible-for-as-large-a-string-as-possible。)

让我们将正则表达式版本扩展为非常强大的https://pypi.python.org/pypi/regex。例如,这支持可变长度的lookbehinds。

3 个答案:

答案 0 :(得分:2)

这应该使用Python的re模块:

(?<=(.))(?=((\w*)(\w*(?!\1)\w\3)\4+))

小提琴:https://regex101.com/r/aA9uJ0/2

注意:

  • 您必须在由虚拟角色扫描的字符串之前;小提琴中的#。如果这是一个问题,应该可以在正则表达式中解决它。
  • 从每个匹配中获取捕获的组2以获取最大周期性子串的集合。
  • Haven没有试过更长的琴弦;表现可能是一个问题。

说明:

  • (?<=(.)) - 查看最大周期子字符串之前的字符;被捕获为第1组
  • (?=...) - 前瞻,以确保匹配重叠的模式;见How to find overlapping matches with a regexp?
  • (...) - 捕获最大周期性子串(组2)
  • (\w*)(\w*...\w\3)\4+ - @ horcruz&#39;正则表达式,由OP提出
  • (?!\1) - 对组1进行否定预测以确保周期性子字符串最大

正如@ClasG指出的那样,我的正则表达式的结果可能不完整。当两次运行以相同的偏移量开始时会发生这种情况例子:

  • aabaab有3次投放:aabaabaaaa。前两次运行以相同的偏移量开始。我的正则表达式将无法返回最短的正则表达式。
  • atatbatatb有3次投放:atatbatatbatatatat。同样的问题;我的正则表达式只会返回第一次和第三次运行。

在正则表达式中这可能无法解决。据我所知,没有正则表达式引擎能够返回两个以相同偏移量开始的不同匹配。

我看到两种可能的解决方案:

  • 忽略丢失的跑步。如果我没有弄错的话,那么它们总是重复的;在相同的封装运行中将遵循相同的运行。
  • 对结果进行一些后处理。对于每次发现的运行(让我们称之为X),扫描之前的运行试图找到相同的字符序列开始的运行(让我们称之为Y)。找到后(并且尚未使用&#39;),添加与X具有相同字符序列的条目,但偏移量为Y.

答案 1 :(得分:0)

我认为这是不可能的。正则表达式无法执行复杂的非确定性作业,即使使用反向引用也是如此。你需要一个算法。

答案 2 :(得分:0)

这种取决于您的输入标准......没有无限的字符串..使用后向引用,您将能够创建您希望匹配的模式的最后出现次数的合适表示。 \ 我个人会定义输入长度的桶,然后填充它们。

然后我会使用自动机来查找存储桶中的模式,然后最终将它们合并为更大的模式。

在这种情况下,RegEx不会有多快,它能够以多快的速度识别模式并消除无效标准。