Arrays 检查两个子串在O(n)时间内是否重叠

Arrays 检查两个子串在O(n)时间内是否重叠,arrays,string,algorithm,Arrays,String,Algorithm,如果我有一个长度为n的字符串S和一个元组列表(a,b),其中a指定S的子字符串的起始位置,b是子字符串的长度。为了检查是否有任何子字符串重叠,我们可以,例如,在触摸它时,在S中标记位置。但是,如果元组列表的大小为n(循环元组列表,然后循环S),我认为这将花费O(n^2)时间 是否有可能检查是否有任何子串在O(n)时间内确实与另一个子串重叠 编辑: 例如,S=“abcde”。元组=[(1,2)、(3,3)、(4,2)],表示“ab”、“cde”和“de”。我想知道在读取(4,2)时发现了重叠 我认

如果我有一个长度为n的字符串S和一个元组列表(a,b),其中a指定S的子字符串的起始位置,b是子字符串的长度。为了检查是否有任何子字符串重叠,我们可以,例如,在触摸它时,在S中标记位置。但是,如果元组列表的大小为n(循环元组列表,然后循环S),我认为这将花费O(n^2)时间

是否有可能检查是否有任何子串在O(n)时间内确实与另一个子串重叠

编辑: 例如,S=“abcde”。元组=[(1,2)、(3,3)、(4,2)],表示“ab”、“cde”和“de”。我想知道在读取(4,2)时发现了重叠

我认为它是O(n^2),因为每次都会得到一个元组,然后需要循环S中的子字符串以查看是否有任何字符被标记为dirty

编辑2: 一旦检测到碰撞,我将无法退出。假设我需要报告所有随后发生冲突的元组,因此我必须循环遍历整个元组列表

编辑3: 算法的高级视图:

 for each tuple (a,b)
   for (int i=a; i <= a+b; i++)
      if S[i] is dirty 
        then report tuple and break //break inner loop only
每个元组(a,b)的


对于(int i=a;i,您的基本方法是正确的,但是您可以优化停止条件,在最坏的情况下,以保证有限的复杂性。这样考虑一下-在最坏的情况下,您需要遍历和标记S中的多少个位置

如果没有冲突,那么在最坏的情况下,您将访问长度(S)位置(由于任何附加的元组都将发生冲突,到那时元组将用完)。如果发生冲突,您可以在第一个标记的对象处停止,因此您再次受到未标记元素的最大数量的限制,即长度(S)

编辑:由于您添加了报告所有冲突元组的要求,让我们再次计算(扩展我的注释)——

一旦标记了所有元素,就可以通过单个步骤(O(1))检测每个进一步元组的冲突,因此需要O(n+n)=O(n)。 这一次,每一步要么标记一个未标记的元素(在最坏的情况下总的n个),要么识别一个冲突的元组(最坏的O(元组),我们假设它也是n个)

实际步骤可以是交错的,因为元组可以以任何方式组织,而不首先发生冲突,但一旦发生冲突(最多n个元组,在第一次冲突之前覆盖所有n个元素),您必须在第一步每次都发生碰撞。其他排列可能会在标记所有元素之前发生碰撞,但同样,您只是在重新排列相同数量的步骤

最坏情况示例:一个元组覆盖整个数组,然后是n-1个元组(不管哪个)—— [(1,n),(n,1),(n-1,1),…(1,1)]

第一个元组需要n个步骤来标记所有元素,其余的每个元组需要O(1)个步骤来完成。总体O(2n)=O(n)。现在请相信下面的示例需要相同数量的步骤-


[(1,n/2-1),(1,1),(2,1),(3,1),(n/2,n/2),(4,1),(5,1)…(n,1)]

根据您的描述和评论,重叠问题可能与字符串算法无关,它可以被视为“段重叠”问题

仅以您的示例为例,它可以转换为3段:[1,2],[3,5],[4,5]。问题是检查这3段是否重叠

假设我们有
m
段,每个段都有格式[start,end],这意味着段的开始位置和结束位置,一种有效的检测重叠的算法是按开始位置升序排序,需要
O(m*lgm)
。然后迭代已排序的
m
段,对于每个段,尝试查找其结束位置,此处您只需检查:

if(start[i] <= max(end[j], 1 <= j <= i-1) {
    segment i is overlap;
}
maxEnd[i] = max(maxEnd[i-1], end[i]); // update max end position of 1 to i

<代码> >(start [i] 这是段重叠问题,如果列表中的元组列表按WRT第一个字段的排序顺序,则该解决方案应该是可能的。
  • 将间隔从(开始,字符数)转换为(开始,包括结束)。因此上述示例变为:
    [(1,2)、(3,3)、(4,2)]==>[(1,2)、(3,5)、(4,5)]

  • 如果转换后的连续元组
    (a,b)
    (c,d)
    始终跟随
    b
    ,则元组有效。否则,上述元组中存在重叠


  • 1
    2
    中的每一项都可以在
    O(n)中完成
    如果数组按上述形式排序。

    我不理解这个问题。时间复杂度怎么可能取决于
    字符串的长度而不是元组列表的长度呢?@pbabcdefp我编辑了这个问题,并添加了为什么我认为它是O(n^2)重叠是什么意思?重叠与元组有关,还是与S有关?你能给出更多的例子吗?@coderz overlap表示如果S的两个子串共享至少一个位置。(3,3)与(4,2)重叠,因为它们“de”(S[4]和S[5],S以1开头)。是否需要报告每次冲突(例如,
    (0,2)
    冲突(1,1)
    (1,1)
    (1,2)
    冲突,而
    (0,2)
    (1,2)
    冲突,还是只需要报告每个有冲突的元组?如果需要报告每个冲突,可能会有多个
    O(n)
    ,并且可能需要花费的时间超过
    O(n)
    只是为了输出所有内容。谢谢您的回答。到和是您的第一个问题,它的长度是否应该是S?例如,第一个元组覆盖了整个S,那么下面的所有元组都将发生碰撞。因此,第一个外循环运行n次,然后下面的运行O(1)时间…..这是否正确?@xcoder,如果外部循环在元组上迭代,那么它将运行一次(在第一个元组上),让内部循环将所有n个元素标记为已接触,然后在第一次检查第二个元组时立即退出,因为它会发生碰撞。也许我应该更清楚地说明这一点。一旦检测到碰撞,我就无法退出。假设我需要报告al