Python程式:查詢最大數量的無重疊子串


假設我們有一個僅包含小寫字母的字串 s,我們需要找到 s 的最大數量的非空子串,這些子串滿足以下規則:

  • 子串不重疊。

  • 包含特定字元 ch 的子串必須包含 ch 的所有出現。

我們需要找到滿足這兩個條件的最大子串數量。如果有多個子串數量相同的解,則返回總長度最小的解。

例如,如果輸入為 s = "pqstpqqprrr",則輸出為 ["s","t","rrr"],因為滿足條件的所有可能的子串為 ["pqstpqqprrr", "pqstpqqp", "st", "s", "t", "rrr"]

為了解決這個問題,我們將遵循以下步驟:

  • right := 對 s 中所有單個字元 ch 的索引位置從右向左排序。

  • left := 對所有 i ∈ right 的字元 s[i] 的索引列表。

  • has := 空列表,gen := 空列表。

  • 對於 i 從 0 到 right 的大小 - 1:

    • 將來自 s[right[i]] 的新字元集插入 gen 的末尾。

    • 將來自 s[從索引 (left[i] + 1 到 right[i]-1) - gen 的最後一項] 的子串的新字元集插入 has 的末尾。

    • 對於 j 從 has 的大小 - 2 到 0:

      • 如果 (has 的最後一項 AND gen[j]) 且 (has[j] AND gen 的最後一項) 不為零,則:

        • gen 的最後一項 := gen 的最後一項 OR gen[j]

        • has 的最後一項 := (has 的最後一項 OR has[j]) - gen 的最後一項

        • 移除 has[j],gen[j]

  • res := 新列表,p_right := -1

  • 對於 ind 從 0 到 has 的大小 - 1:

    • l := 如果 s[i] 出現在 gen[ind] 中,則所有 i ∈ left 的元素 i 的最小值。

    • r := 如果 s[i] 出現在 gen[ind] 中,則所有 i ∈ right 的元素 i 的最大值。

    • 如果 p_right < l,則:

      • 將 s[從索引 l 到 r] 的子串插入 res 的末尾。

      • p_right := r

  • 返回 res

示例

讓我們看下面的實現來更好地理解。

def solve(s):
   right = sorted([s.rindex(ch) for ch in set(s)])
   left = [s.index(s[i]) for i in right]
 
   has, gen = [], []
   for i in range(len(right)):
      gen.append(set(s[right[i]]))
      has.append(set(s[left[i] + 1:right[i]]) - gen[-1])

   for j in range(len(has) - 2, -1, -1):
      if (has[-1] & gen[j]) and (has[j] & gen[-1]):
         gen[-1] = gen[-1] | gen[j]
         has[-1] = (has[-1] | has[j]) - gen[-1]
         del has[j], gen[j]

   res, p_right = [], -1
   for ind in range(len(has)):
      l = min([i for i in left if s[i] in gen[ind]])
      r = max([i for i in right if s[i] in gen[ind]])
      if p_right < l:
         res.append(s[l : r + 1])
         p_right = r

   return res

s = "pqstpqqprrr"
print(solve(s))

輸入

"pqstpqqprrr"

輸出

['s', 't', 'rrr']

更新於:2021年10月6日

562 次瀏覽

開啟你的職業生涯

完成課程獲得認證

開始學習
廣告