gpt4 book ai didi

java - LCP如何帮助查找模式的出现次数?

转载 作者:太空狗 更新时间:2023-10-29 22:32:59 24 4
gpt4 key购买 nike

我已经读过最长公共(public)前缀(LCP)可用于查找字符串中某个模式出现的次数。

具体来说,您只需要创建文本的后缀数组,对其进行排序,然后无需进行二进制搜索来找到范围,从而可以计算出出现的次数,则只需为文本中每个连续的条目计算LCP后缀数组。

尽管使用二进制搜索来查找模式的出现次数很明显,但我无法弄清楚LCP如何在这里帮助找到发生次数。

例如,banana的后缀数组:

LCP  Suffix entry
N/A a
1 ana
3 anana
0 banana
0 na
2 nana

LCP如何帮助找到像“香蕉”或“na”之类的子字符串出现的次数对我来说并不明显。

是否有帮助弄清楚LCP在这里有什么帮助?

最佳答案

我不知道使用LCP数组而不执行二进制搜索的任何方法,但是我相信您所指的是Udi Manber和Gene Myers在Suffix arrays: a new method for on-line string searches中描述的技术。

(注意:以下说明已复制到2014年4月9日的Wikipedia文章中,请参见diff。如果您在此处和Wikipedia上查看修订历史,则会发现此处的修订是第一个编写的。请不要插入诸如“取自Wikipedia”之类的评论添加到我的答案中。)

这个想法是这样的:为了找到在文本T(长度N)中给定字符串P(长度m)的出现次数,

  • 您对T的后缀数组使用二进制搜索(就像您建议的那样)
  • 但是您可以使用LCP数组作为辅助数据结构来加快的速度。更具体地说,您将生成LCP阵列的特殊版本(以下将其称为LCP-LR)并使用它。

  • 使用标准二进制搜索(不提供LCP信息)的问题是,在 中,您需要进行每个O(log N)比较,将P与后缀数组的当前条目进行比较,这意味着 完整字符串比较,最多m个字符。因此复杂度为O(m * log N)。

    LCP-LR阵列可以通过以下方式将其提高到O(m + log N):
  • 在二进制搜索算法的任何时候,您都像往常一样考虑后缀数组的范围(L,...,R)及其中心点M,并确定是否在左侧子范围中继续搜索(L,...,M)或在右子范围(M,...,R)中。
  • 为了做出决定,将P与M处的字符串进行比较。如果P与M相同,则可以完成,但如果不相同,则将比较P的前k个字符,然后确定P在字典上是否较小或大于M。我们假设结果是P大于M。
  • 因此,在下一步 中,考虑(M,...,R)和中间的新中心点M':
                  M ...... M' ...... R
    |
    we know:
    lcp(P,M)==k

    技巧现在是对LCP-LR进行了预先计算,以便通过O(1)查找可以告诉您M和M'的最长公共(public)前缀lcp(M,M')。

    您已经知道(从上一步开始)M本身与P共同具有k个字符的前缀:lcp(P,M)= k。现在有三种可能性:
  • 情况1:k
  • 情况2:k> lcp(M,M'),即P与M共有的前缀字符多于M与M'共有的前缀字符。因此,如果我们将P与M'进行比较,则公共(public)前缀将小于k,而M'在字典上大于P,因此,在没有进行实际比较的情况下,我们继续左半部分(M,.. 。,M')。
  • 情况3:k == lcp(M,M')。因此,M和M'在前k个字符中都与P相同。要确定我们是继续左半边还是右半边,只需从第(k + 1)个字符开始将P与M'比较即可。
  • 我们以递归方式继续。

  • 总体效果是没有将P的任何字符与文本的任何字符进行多次比较。字符比较的总数以m为界,因此总复杂度确实为O(m + log N)。

    显然,剩下的关键问题是我们如何预先计算LCP-LR,以便它能够在O(1)时间告诉我们后缀数组的任意两个条目之间的lcp?如您所说,标准LCP数组仅告诉您连续条目lct的lct ,即任何x的lcp(x-1,x)。但是,上面描述中的M和M'不一定是连续的条目,那么该怎么做?

    这样做的关键是要认识到在二进制搜索过程中只会出现某些范围(L,...,R):它始终以(0,...,N)开头,并在中心进行除法,然后继续向左或向右继续,然后再将其一半除以此类推。如果考虑到这一点:在二进制搜索过程中,后缀数组的每个条目都恰好是一个可能范围的中心点。因此,恰好有N个不同的范围(L ... M ... R)可能在二分查找中起作用,对于这N个可能的范围,预先计算lcp(L,M)和lcp(M,R)就足够了范围。因此,这是2 * N个不同的预先计算的值,因此LCP-LR的大小为O(N)。

    此外,有一个简单的递归算法可以从标准LCP数组计算O(N)时间中LCP-LR的2 * N值–如果您需要对此进行详细说明,建议您提出一个单独的问题。

    总结一下:
  • 可以根据LCP
  • 在O(N)时间和O(2 * N)= O(N)空间中计算LCP-LR
  • 在二进制搜索过程中使用LCP-LR有助于将搜索过程从O(M * log N)加速到O(M + log N)
  • 根据您的建议,可以使用两个二进制搜索来确定P的匹配范围的左端和右端,并且匹配范围的长度与P的出现次数相对应。

  • 关于java - LCP如何帮助查找模式的出现次数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11373453/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com