最长的共享部分算法

时间:2017-02-27 16:52:56

标签: algorithm string-matching

我有一个相当大的数字(1000s)的字符串,比如说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个位置。

是否有一种有效的算法可以让我找到执行此操作的字符串对(或更多)?我不认为它是完全一个字符串匹配的东西,比如最长的常见子字符串问题,因为这些字符串具有特定的对齐方式。

注意,对于它的价值而言,这只是一个较大算法的一小部分,它重复这样做,将共享长度合并在一起形成一个新的字符串,以便在下一次迭代中,我会< / p>

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,&amp; S_3从位置3-6共享一个部分,给出

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

等等

2 个答案:

答案 0 :(得分:0)

首先,答案总是在2个字符串之间。如果这个&#34; 其中2个(或更多)字符串共享相同的连续下划线长度,则不可能有超过2个字符串,其序列长于匹配的最佳2个字符串。&#39 ;是正确的要求。 所以问题是找到在同一位置具有最长_序列的最长的2个字符串。要做到这一点,你必须这样做:

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

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

  3. 一个。如果该区间在j区间的左侧

    ,则增加i

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

    ℃。如果他们离开它是平等的,那么你增加的人并不重要。

    1. 始终将找到的交点与最大值进行比较,并在交点较大时更改最大值。
    2. 优化: 1.对于每个区间数组,当你有2个字符串并且想要比较时,请记住最长的区间,如果其中一个字符串具有较小的“最大”字符串。间隔超过你不做算法的最大值,它不会提高最大值。

      它的复杂性是O(N ^ 2 *(O(len(S1)+ len(S2)+ ... + len(Sn)))因为只有step1遍历所有字符。 2经历了间隔。

答案 1 :(得分:0)

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

有一个整数数组,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

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