二分查詢高效判定子串行

2022-07-04 01:30:19 字數 3154 閱讀 7962

392.判斷子串行

-----------

二分查詢本身不難理解,難在巧妙地運用二分查詢技巧。對於乙個問題,你可能都很難想到它跟二分查詢有關,比如前文 最長遞增子串行 就借助乙個紙牌遊戲衍生出二分查詢解法。

今天再講一道巧用二分查詢的演算法問題:如何判定字串s是否是字串t的子串行(可以假定s長度比較小,且t的長度非常大)。舉兩個例子:

s = "abc", t = "ahbgdc", return true.

s = "axc", t = "ahbgdc", return false.

題目很容易理解,而且看起來很簡單,但很難想到這個問題跟二分查詢有關吧?

首先,乙個很簡單的解法是這樣的:

bool issubsequence(string s, string t) 

return i == s.size();

}

其思路也非常簡單,利用雙指標i, j分別指向s, t,一邊前進一邊匹配子串行:

讀者也許會問,這不就是最優解法了嗎,時間複雜度只需 o(n),n 為t的長度。

是的,如果僅僅是這個問題,這個解法就夠好了,不過這個問題還有 follow up

如果給你一系列字串s1,s2,...和字串t,你需要判定每個串s是否是t的子串行(可以假定s較短,t很長)。

boolean issubsequence(string sn, string t);
你也許會問,這不是很簡單嗎,還是剛才的邏輯,加個 for 迴圈不就行了?

可以,但是此解法處理每個s時間複雜度仍然是 o(n),而如果巧妙運用二分查詢,可以將時間複雜度降低,大約是 o(mlogn)。由於 n 相對 m 大很多,所以後者效率會更高。

ps:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的演算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種演算法套路後投再入題海就如魚得水了。

二分思路主要是對t進行預處理,用乙個字典index將每個字元出現的索引位置按順序儲存下來:

int m = s.length(), n = t.length();

arraylist index = new arraylist[256];

// 先記下 t 中每個字元出現的位置

比如對於這個情況,匹配了 "ab",應該匹配 "c" 了:

按照之前的解法,我們需要j線性前進掃瞄字元 "c",但借助index中記錄的資訊,可以二分搜尋index[c]中比 j 大的那個索引,在上圖的例子中,就是在[0,2,6]中搜尋比 4 大的那個索引:

這樣就可以直接得到下乙個 "c" 的索引。現在的問題就是,如何用二分查詢計算那個恰好比 4 大的索引呢?答案是,尋找左側邊界的二分搜尋就可以做到。

ps:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的演算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種演算法套路後投再入題海就如魚得水了。

在前文 二分查詢詳解 中,詳解了如何正確寫出三種二分查詢演算法的細節。二分查詢返回目標值val的索引,對於搜尋左側邊界的二分查詢,有乙個特殊性質:

val不存在時,得到的索引恰好是比val大的最小元素索引

什麼意思呢,就是說如果在陣列[0,1,3,4]中搜尋元素 2,演算法會返回索引 2,也就是元素 3 的位置,元素 3 是陣列中大於 2 的最小元素。所以我們可以利用二分搜尋避免線性掃瞄。

// 查詢左側邊界的二分查詢

int left_bound(arraylistarr, int tar) else

}return lo;

}

以上就是搜尋左側邊界的二分查詢,等會兒會用到,其中的細節可以參見前文《二分查詢詳解》,這裡不再贅述。

這裡以單個字串s為例,對於多個字串s,可以把預處理部分抽出來。

boolean issubsequence(string s, string t) 

// 串 t 上的指標

int j = 0;

// 借助 index 查詢 s[i]

for (int i = 0; i < m; i++)

return true;

}

演算法執行的過程是這樣的:

可見借助二分查詢,演算法的效率是可以大幅提公升的。

_____________

逐步增加遞增子串行 二分查詢的妙用 判定子串行

labuladong 二分查詢本身不難理解,難在巧妙地運用二分查詢技巧。對於乙個問題,你可能都很難想到它跟二分查詢有關,比如前文 最長遞增子串行就借助乙個紙牌遊戲衍生出二分查詢解法。今天再講一道巧用二分查詢的演算法問題 如何判定字串s是否是字串t的子串行 可以假定s長度比較小,且t的長度非常大 舉兩...

迭代二分查詢二分查詢

在寫這篇文章之前,已經寫過了幾篇關於改迭代二分查詢主題的文章,想要了解的朋友可以去翻一下之前的文章 bentley在他的著作 writing correct programs 中寫道,90 的計算機專家不能在2小時內寫出完整確正的二分搜尋演算法。難怪有人說,二分查詢道理單簡,甚至小學生都能明確。不過...

1128 二分 二分查詢

時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述nettle最近在玩 艦 因此nettle收集了很多很多的船 這裡我們假設nettle氪了很多金,開了無數個船位 去除掉重複的船之後,還剩下n 1 n 1,000,000 種不同的船。每一艘船有乙個稀有值,任意兩艘船的稀有...