【问题标题】:Longest shared section algorithm最长共享部分算法
【发布时间】:2017-02-27 16:52:55
【问题描述】:

我有相当多(1000 个)的字符串,比如 S_1...S_n,其中的字符只取 2 个值——比如为了便于可视化“”(空格)或“_”(下划线)。

S_1:  _______ ____ __ _____ ___
S_2:     _______ _____ ___
S_3:     _____________
S_4:    ____ _____________

posi- 01234567890123456789012345...
tion  0         1         2

我想找到最长的一段,其中 2 个(或更多)字符串共享相同的连续下划线长度。在上面的例子中,它是 S_3 和 S_4 之间从位置 7 到 15 共享的部分,包括 9 个位置。

是否有一种有效的算法可以让我找到执行此操作的一对(或更多)字符串?我不认为这是相当字符串匹配的事情,就像最长的公共子字符串问题一样,因为这些字符串具有特定的对齐方式。

请注意,对于它的价值,这只是一个更大的算法的一小部分,它重复执行此操作,将共享长度合并在一起形成一个新字符串,因此在下一次迭代中,我会

S_1:  _______ ____ __ _____ ___
S_2:     _______ _____ ___
S_3:     ____
S_4:    ____          ___
S_N+1:       _________

然后我会重复算法以找到(在这种情况下)S_2 和新的 S_N+1 共享下一个最长的部分,从位置 11-15,形成

S_1:  _______ ____ __ _____ ___
S_2:     _______       ___
S_3:     ____
S_4:    ____          ___
S_N+1:       ____
S_N+2:           _____

然后 S_1、S_2 和 S_3 从位置 3-6 共享一个部分,给出

S_1:  ___     ____ __ _____ ___
S_2:         ___       ___
S_3:         
S_4:    ____          ___
S_N+1:       ____
S_N+2:           _____
S_N+3:   ____

等等

【问题讨论】:

  • 不是一个真正聪明或快速的解决方案,但它可能会有所帮助。将字符串转换为二进制数并使用And(按位运算)en.wikipedia.org/wiki/Bitwise_operations_in_C 进行比较,然后遍历新创建的数组并找到最长的 1 或 0。
  • 是的,直到我达到最大位长。不过,我认为有一些库允许任意长度的位数组。请注意,我很乐意通过存储间隔而不是字符串本身来做到这一点(实际上,字符串只是表示集合列表中存在或不存在某些数字。

标签: algorithm string-matching


【解决方案1】:

首先,答案总是在两个字符串之间。如果此“其中 2 个(或更多)字符串共享相同的连续下划线长度。”是正确的要求,则不可能有 2 个以上的字符串具有比匹配的最佳 2 个更长的序列。 所以问题是找到最长的 2 个字符串,它们在同一位置具有最长的 _ 序列。为此,您必须这样做:

  1. 获取每个字符串并为 _ 的每个存储桶创建另一个具有索引对的字符串 例如:对于 _ ___ _____,您的区间数组将是 [0,0]、[2,4] [5,9]

  2. 取 2 个字符串的所有组合并取 2 个索引(i 代表 string1,j 代表 string2)。您需要做的是以一种智能的方式移动每个索引。首先两者都是 0,并且在每一步你都在问自己是否可以将索引 i 的间隔与索引 j 的间隔相交,这样你就可以得到这两个间隔的最佳子序列。 完成交叉后,您有 2 个选项:增加 i 或增加 j

一个。如果该区间在 j 区间的左边,则增加 i

b.如果该区间在 i 区间的左侧,则增加 j。

c。如果他们的左边是平等的,你增加谁并不重要。

  1. 始终将找到的交叉点与最大值进行比较,如果交叉点较大,则更改最大值。

优化: 1. 对于每个间隔数组,当您有 2 个字符串并想要比较时,请记住最长的间隔,如果其中一个字符串的“最大”间隔小于最大值,则您不执行算法,它将不提高最大值。

复杂度是 O(N^2 * (O(len(S1) + len(S2) + ... + len(Sn)) ) 因为只有 step1 遍历所有字符。而 Step 2 遍历间隔。

【讨论】:

  • "2. 取 2 个字符串的所有组合" - 这不是让这个算法至少 O(n^2) 吗?
  • 拍摄,是的,它是 O(N^2 * (O(len(S1) + len(S2) + ... + len(Sn)) )。现在我也在想更快的解决方案可能只是将所有间隔放入一个数组中,然后遍历它们并发生 2 个事件: 0. 按起点对间隔进行排序 1. 如果起点为间隔,则将间隔的开始添加到队列中2. 从队列中删除一个区间然后到达终点。当你删除一个区间时,只需检查队列中的最小值,差值是交集(你与最大值比较)。使用 minHeap 而不是常规排队。
  • 您将不得不发生另一组事件。只需在此处添加所有值(开始,间隔结束并对它们进行排序)当您浏览它们时,您会应用我在上一个评论中所说的内容(步骤 1 和步骤 2,具体取决于值的大小写)
  • 那应该是 (O((len(S1) + len(S2) + ... + len(Sn)) * log(len(S1) + len(S2) + .. . + len(Sn)))
  • @Marius 感谢您的关注和跟进。将尝试实施并报告。
【解决方案2】:

我将假设所有字符串的长度相同,尽管您可以根据需要填充它们以使其正常工作。

有一个与字符串长度相同的整数数组 A,初始化为全 -1。 A[i] 的值将是从 i 使用所有下划线可以达到的最大索引。也就是说,如果 A[i] == k,那么有一些字符串使得该字符串中的 A[i]..k 完全是下划线。

bestOverall := -1
For each string, S:
  maxPos := -1
  for i := len(S); i >= 0; i--:
    if S[i] == '_' && maxPos < 0:
        // We were previously look at ' ', now we're looking at '_', so store
        // the highest index that happened at in this particular run.
        maxPos = i
    if S[i] == ' ':
        maxPos = -1
    if min(A[i]-i, maxPos-i) > bestOverall:
        // This is the crux of it all.  A[i]-i is the length of consecutive '_'
        // you've seen in a single string before, starting at this position.
        // maxPos-i is the length of consecutive '_' you've seen in this string,
        // starting at this position.  If this length is greater than your
        // previous best, keep track of it.  Presumably you also might want to
        // store which strings were involved, which would take extra storage.
        bestOverall = min(A[i]-i, maxPos-i)
    if maxPos >= A[i]:
        // If you're doing better with this string than previous iterations,
        // keep track of it.
        A[i] = maxPos

在这个 bestOverall 的末尾将是你可以用两个字符串得到的最长的下划线。您可以保留一个辅助数组来跟踪所涉及的第一个字符串,并在每次更新最佳时存储第一个和第二个所涉及的字符串。这是 O(N*S),其中 N 是字符串的数量,S 是字符串的长度。假设您的字符串采用这种格式而不是间隔列表,这是您能做的最好的事情。如果它们确实以间隔列表的形式出现,那么您可能会做得更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 2012-12-11
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多