String 如何找到字符串的句点

String 如何找到字符串的句点,string,algorithm,substring,String,Algorithm,Substring,我从用户那里获取一个输入,它是一个带有特定子字符串的字符串,该子字符串在整个字符串中重复。我需要输出子字符串或其长度(即周期) 说 我可以从一个字符开始,检查它是否与下一个字符相同,如果不是,我可以用两个字符,然后用三个字符,依此类推。这将是一个O(N^2)算法。我想知道是否有更优雅的解决方案。如果输入字符串中的每个字符都是重复子字符串的一部分,那么您所要做的就是存储第一个字符,并将其与字符串的其余字符逐个进行比较。如果找到匹配项,则字符串直到匹配一个是您的重复字符串。您可以在线性时间内为整个字

我从用户那里获取一个输入,它是一个带有特定子字符串的字符串,该子字符串在整个字符串中重复。我需要输出子字符串或其长度(即周期)


我可以从一个字符开始,检查它是否与下一个字符相同,如果不是,我可以用两个字符,然后用三个字符,依此类推。这将是一个O(N^2)算法。我想知道是否有更优雅的解决方案。

如果输入字符串中的每个字符都是重复子字符串的一部分,那么您所要做的就是存储第一个字符,并将其与字符串的其余字符逐个进行比较。如果找到匹配项,则字符串直到匹配一个是您的重复字符串。

您可以在线性时间内为整个字符串构建后缀树(后缀树很容易在线查找),然后递归计算并存储后缀树的每个内部节点v下的后缀树叶数(后缀前缀的出现次数)N(v)。还递归地计算并存储树的每个节点上每个后缀前缀L(v)的长度。然后,在树中的内部节点v处,在v处编码的后缀前缀是一个重复的子序列,如果N(v)等于字符串的总长度除以L(v),则会生成字符串。

让我假设字符串
N
的长度至少是句点
p
的两倍

算法

  • m
    =1,让
    S
    代表整个字符串
  • m
    =m*2
    • 查找子字符串S[:m]的下一个匹配项
    • k
      作为下一个事件的开始
    • 检查S[:k]是否为周期
    • 如果没有,请转到2
  • 示例

    假设我们有一根绳子

    CDCDFBFCDCDFDFCDCDFBFCDCDFDFCDC
    
    对于2的每一次幂
    m
    ,我们可以找到前
    2^m
    字符的重复。然后我们将这个序列扩展到它的第二次出现。让我们从2^1 so
    CD
    开始

    CDCDFBFCDCDFDFCDCDFBFCDCDFDFCDC
    CDCD   CDCD   CDCD   CDCD   CD
    
    CDCDFBFCDCDFDFCDCDFBFCDCDFDFCDC
    CDCD   CDCD
    
    我们不扩展
    CD
    ,因为下一个事件就在那之后。但是
    CD
    不是我们正在寻找的子字符串,所以让我们来看看下一个幂:
    2^2=4
    和子字符串
    CDCD

    CDCDFBFCDCDFDFCDCDFBFCDCDFDFCDC
    CDCD   CDCD   CDCD   CDCD   CD
    
    CDCDFBFCDCDFDFCDCDFBFCDCDFDFCDC
    CDCD   CDCD
    
    现在让我们将字符串扩展到第一个重复。我们得到

    CDCDFBF
    
    我们检查这是否是周期性的。事实并非如此,我们要走得更远。我们尝试2^3=8,所以
    cdcdcdfbfc

    CDCDFBFCDCDFDFCDCDFBFCDCDFDFCDC
    CDCDFBFC      CDCDFBFC      
    
    我们试图扩展,我们得到了

    CDCDFBFCDCDFDF
    
    这确实是我们的时代

    我希望这能在O(nlogn)中使用类似于KMP的算法来检查给定字符串出现的位置。请注意,此处仍应计算一些边缘情况

    直觉上这应该是可行的,但我的直觉在这个问题上已经失败了一次,所以如果我错了,请纠正我。我会设法找出一个证据


    这是一个很好的问题。

    通过归纳计算字符串的每个前缀的周期,可以在线性时间和恒定的额外空间中实现这一点。我记不起细节(有几件事情需要纠正),但你可以在中找到它们。

    我也一直在寻找这个问题的时空最优解决方案。基本上看起来是这样的,但我想解释一下它到底是关于什么的,以及一些进一步的发现

    首先,我提出的这个问题提出了一个看似有希望但不正确的解决方案,并说明了其不正确的原因:

    一般来说,“查找周期”问题相当于“查找自身内的模式”(在某种意义上是“
    strstr(x+1,x)
    ”),但没有超过其结束的约束匹配。这意味着您可以通过采用任何从左到右的字符串匹配算法,并将其应用于自身,将到达草堆/文本末尾的部分匹配视为匹配,来找到周期,并且时间和空间要求与您使用的任何字符串匹配算法相同

    tmyklebu的回答中引用的方法实质上也是将这一原则应用于。另一个时空最优解决方案应该可以使用

    不幸的是,这个相当著名且简单的算法不是一个解决方案,因为它不是从左到右的。特别是,左因子失配后的推进取决于右因子已经匹配,并且不可能与右因子模右因子的周期未对齐的另一个匹配。当在模式本身中搜索并忽略结束后的任何内容时,我们无法确定下一个右因子匹配的发生时间(部分或全部右因子可能已经移动到模式结束后),因此无法进行保留线性时间的移动


    当然,如果工作空间可用,可以使用许多其他算法。KMP是具有O(n)空间的线性时间,可以将其调整为仅具有对数空间的合理有效时间。

    为什么S2子串不是AB?现在我对S3感到困惑。ABC不重复,或者这也是一个打字错误?对不起,我太挑剔了,我只是想弄清楚你到底想要输出什么。输入字符串中的每个字符都是重复子字符串的一部分。不管字符串的长度是多少@csmckelveyFor字符串“ababababxxxxabababababxxxx”tortoise and hare为您提供句点2,而实际句点为10。您能否给出一个代码示例,说明这如何适用于两个输入?伙计。阅读我问题中示例下面的一段文字:|哦,我没看到。但既然您说它必须包含一个循环,那么该方法的复杂性将是O(N),因为在最坏的情况下,您只是将第一个字符与整个字符串进行比较@csmckelvey伪代码如下:
    charfirst=input[0];字符串重复字符串=第一个;int i=1;char nextChar=输入[i];while(first!=nextChar){repeatingString+=nextChar;i++;nextChar=input