计算字符串的运行


11

请考虑以下W. Rytter 摘自字符串运行次数的定义。请注意,单词,字符串和子字符串大致都是同义词。

字符串中的游程是字符串中不可扩展的(具有相同的最小周期)周期段。

单词w的周期p是任何正整数p,因此只要定义了该方程式的两边,w [i] = w [i + p]。令per(w)表示w的最小周期的大小。我们说单词w是周期iff per(w)<= | w | / 2。

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

字符串w中的游程(或最大周期性)是一个区间[i ... j],其中j> = i,使得

  • w [i ... j]是周期为p = per(w [i ... j])的周期词
  • 最大。形式上,w [i-1] = w [i-1 + p]或w [j + 1] = w [j + 1-p]都不是。非正式地,该运行不能包含在相同期间的较大运行中。

用RUNS(w)表示w的行程集。

例子

的四次运行atattatt是[4,5] = tt,[7,8] = tt,[1,4] = atat,[2,8] = tattatt。

该字符串aabaabaaaacaacac包含以下7个运行:

[1,2] = aa,[4,5] = aa,[7,10] = aaaa,[12,13] = aa,[13,16] = acac,[1,8] = aabaabaa,[9 ,15] = aacaaca。

您的输出应为运行清单。每次运行都应指定其代表的间隔,但不需要输出子字符串本身。确切的格式可以是您方便使用的任何格式。

这些示例使用1索引,但是如果更方便,则可以随意使用0索引。

任务

编写给定字符串w的代码,输出RUNS(w)。

语言和输入

您可以使用任何喜欢的语言,并以最方便的任何形式获取输入字符串。但是,您必须提供完整的程序,并应在示例输入上显示运行代码的示例。


4
很好的挑战,但是是否有充分的理由推翻默认和禁止功能?
Martin Ender

@MartinEnder这只是我的偏爱。它使人们更轻松地复制和粘贴代码并自己尝试一下,从而使答案对更多的人来说更加有趣。

4
但是,这也会导致大量开销代码,这使得竞争对具有冗长语法的语言不公平。例如,如果我class A{public static ...}每次必须写高尔夫代码时,我就不会打Java 高尔夫
Bassdrop Cumberwubwubwub

@BassdropCumberwubwubwub我可以看到优点和缺点。我碰巧更加权衡了职业选手。我认为最有趣的是在任何情况下都以类似语言比较高尔夫球答案的长度,而不是例如将APL与Python进行比较。

“如果一个运行未完全包含在任何较大的运行中,则该运行是最大的”,但在您的第一个示例中,[7,8]被完全包含在[2,8]中。还是您严格地讲重复相同子字符串的运行?
aidtsu退出是因为SE是EVIL

Answers:


2

Pyth,38个字节

{smm,hk+ekdfgaFTdcx1xM.ttB+0qVQ>QdZ2Sl

  m                                 SlQ   map for d in [1, …, len(input)]:
                            qVQ>Qd          pairwise equality of input[:-d] and input[d:]
                        tB+0                duplicate this list, prepending 0 to one copy
                      .t          Z         transpose, padding with 0
                    xM                      pairwise xor
                  x1                        find all occurrences of 1
                 c                 2        chop into groups of 2
           f                                filter for groups T such that:
             aFT                              the absolute difference between its elements
            g   d                             is greater than or equal to d
   m                                        map for groups k:
     hk                                       first element
    ,  +ekd                                   pair with the last element plus d
 s                                        concatenate
}                                         deduplicate

测试套件


我从“ attattatt”得到“ [[3,5],[6,8],[0,4],[1,8]]”。[3,5]代表“ tt”吗?如果您可以在较高层次上解释所使用的算法,那就太好了。

@Lembik是的,[i, j]表示从(0索引)字符i-1i与字符之间结束j-1j。这应该是Pyth和大多数理智的语言的标准约定(请参见此处此处)。
Anders Kaseorg '16

大。是否可以直观地描述您的解决方案?不幸的是,我无法对您的代码进行反向工程。

1
@Lembik假设我们正在寻找周期d的运行。我们找到字符i与字符i + d匹配的所有位置。然后,我们发现至少d个连续的此类位置的运行。对所有重复d。最后,我们必须删除重复数据,因为实际周期可能只是d的因数。
Anders Kaseorg '16

1

果酱,66

q:A,2m*{~A>_@)_@<2*@@2*<=},{_2$-2>2,.+={+}&}*]{[_1=\)\0=2*)+]}%_&p

在线尝试

简要说明:

该算法分为4个步骤(其中前3个对应于您可以观察到的3个主要模块):

  1. 查找与重复的子字符串相对应的所有[长度索引]对(例如 aba aba aaacaacac);这些是运行的一部分。
  2. 串联属于同一行程的对,即连续索引和相同长度/周期。
  3. 通过采用最小索引和最大索引+ 2 *长度-1来构建实际的运行。
  4. 最后,删除重复的运行(它们是在不同时间段获得的相同间隔)

我想打更多的高尔夫球,所以这都可能会改变。


这次真是万分感谢。您能解释一下您使用的算法吗?

1
@Lembik好的,已更新
aditsu退出是因为SE是EVIL
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.