日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【译】Swift算法俱乐部-Boyer-Moore字符串搜索

發布時間:2025/7/25 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【译】Swift算法俱乐部-Boyer-Moore字符串搜索 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文是對 Swift Algorithm Club 翻譯的一篇文章。

Swift Algorithm Club是 raywenderlich.com網站出品的用Swift實現算法和數據結構的開源項目,目前在GitHub上有18000+??,我初略統計了一下,大概有一百左右個的算法和數據結構,基本上常見的都包含了,是iOSer學習算法和數據結構不錯的資源。

?andyRon/swift-algorithm-club-cn是我對Swift Algorithm Club,邊學習邊翻譯的項目。由于能力有限,如發現錯誤或翻譯不妥,請指正,歡迎pull request。也歡迎有興趣、有時間的小伙伴一起參與翻譯和學習?。當然也歡迎加??,?????。

本文的翻譯原文和代碼可以查看?swift-algorithm-club-cn/Boyer-Moore String Search


Boyer-Moore字符串搜索(Boyer-Moore String Search)

這個主題已經有教程 here

目標:在純Swift中編寫字符串搜索算法,而無需導入Foundation或使用NSString的rangeOfString()方法。

換句話說,我們想在String上實現一個indexOf(pattern:String)擴展,它返回在字符串里面第一次出現搜索模式的String.Index,如果找不到模式則返回nil 。

例子:

// Input: let s = "Hello, World" s.indexOf(pattern: "World")// Output: <String.Index?> 7// Input: let animals = "?????" animals.indexOf(pattern: "?")// Output: <String.Index?> 6 復制代碼

注意: 牛的索引是6,而不是你想象的3,因為字符串為表情符號使用更多的存儲空間。String.Index的實際值并不那么重要,只是它指向字符串中的正確字符。

暴力方法工作正常,但效率不高,尤其是在大塊文本上。 事實證明,您不需要從源字符串中查看 每個 字符 —— 通常可以跳過多個字符。

這種跳過算法被稱為Boyer-Moore算法,它已存在很長時間了。它被認為是所有字符串搜索算法的基準。

以下是您在Swift中編寫它的方法:

extension String {func index(of pattern: String) -> Index? {let patternLength = pattern.countguard patternLength > 0, patternLength <= self.count else { return nil }var skipTable = [Character: Int]()for (i, c) in pattern.enumerated() {skipTable[c] = patternLength - i - 1}let p = pattern.index(before: pattern.endIndex)let lastChar = pattern[p]var i = index(startIndex, offsetBy: patternLength - 1)func backwards() -> Index? {var q = pvar j = iwhile q > pattern.startIndex {j = index(before: j)q = index(before: q)if self[j] != pattern[q] { return nil }}return j}while i < endIndex {let c = self[i]if c == lastChar {if let k = backwards() { return k }i = index(after: i)} else {i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex}}return nil} } 復制代碼

該算法的工作原理如下。 讓源字符與搜索模式字符頭部對齊排列,并查看字符串中的哪個字符與搜索模式的 最后 字符匹配:

source string: Hello, World search pattern: World^ 復制代碼

有三種可能性:

  • 這兩個字符是相同的。 你找到了可能的匹配。

  • 字符不相等,但源字符確實有出現在搜索模式其他位置中。

  • 源字符完全沒有出現在搜索模式中。

  • 在示例中,字符o和d不匹配,但o確實出現在搜索模式中。 這意味著我們可以跳過幾個位置:

    source string: Hello, World search pattern: World^ 復制代碼

    注意兩個o字符現在是如何對齊的。 再次,您將搜索模式的最后一個字符與搜索文本進行比較:W vsd。 它們是不相同的,但W確實出現在搜索模式中。 因此,再次跳過一個位置,讓兩個W字符在相同位置:

    source string: Hello, World search pattern: World^ 復制代碼

    這次兩個字符相等并且可能匹配。 要驗證匹配,您需要進行暴力搜索,但是從搜索模式的末尾開始向前搜索。 這就是它的全部。

    在任何給定時間跳過的數量由“跳過表”確定,“跳過表”是搜索模式中所有字符的字典和跳過的數量。 示例中的跳過表如下所示:

    W: 4 o: 3 r: 2 l: 1 d: 0 復制代碼

    字符越接近模式的末尾,跳過量越小。 如果某個字符在模式中出現多次,則最接近該模式結尾的字符將確定該字符的跳過值。

    注意: 如果搜索模式只包含幾個字符,則執行暴力搜索會更快。 在構建跳過表與為短模式執行暴力搜索之間需要進行權衡。

    致謝:此代碼基于1989年7月Dr Dobb's雜志發表的文章"Faster String Searches" by Costas Menico —— 對 ,1989年! 有時保留那些舊雜志是有用的。

    擴展閱讀:這個算法的詳細分析

    Boyer-Moore-Horspool 算法

    上面算法的一個變體是Boyer-Moore-Horspool 算法。

    像常規的Boyer-Moore算法一樣,它使用skipTable來跳過許多字符。 不同之處在于我們如何檢查局部匹配。在上面的版本中,如果找到了部分匹配,但不是完全匹配,我們只跳過一個字符。在這個修訂版本中,我們也在那種情況下使用跳過表。

    這是Boyer-Moore-Horspool算法的一個實現:

    extension String {func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? {let patternLength = pattern.countguard patternLength > 0, patternLength <= self.count else {return nil}var skipTable = [Character: Int]()for (i, c) in pattern.enumerated() {skipTable[c] = patternLength - i - 1}let p = pattern.index(before: pattern.endIndex)let lastChar = pattern[p]var i = index(startIndex, offsetBy: patternLength - 1)func backwards() -> Index? {var q = pvar j = iwhile q > pattern.startIndex {j = index(before: j)q = index(before: q)if self[j] != pattern[q] { return nil }}return j}while i < endIndex {let c = self[i]if c == lastChar {if let k = backwards() { return k }if !usingHorspoolImprovement {i = index(after: i)} else {let jumpOffset = max(skipTable[c] ?? patternLength, 1)i = index(i, offsetBy: jumpOffset, limitedBy: endIndex) ?? endIndex}} else {i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex}}return nil} } 復制代碼

    在實踐中,Horspool版本的算法往往比原始版本略好一些。 但是,這取決于你愿意做出什么樣的權衡。

    致謝:此代碼基于論文:R. N. Horspool (1980). "Practical fast searching in strings". Software - Practice & Experience 10 (6): 501–506.

    作者:Matthijs Hollemans,Andreas Neusü?,Matías Mazzei
    翻譯:Andy Ron
    校對:Andy Ron

    譯注: 阮一峰老師的文章 字符串匹配的Boyer-Moore算法 講的比較清晰。

    總結

    以上是生活随笔為你收集整理的【译】Swift算法俱乐部-Boyer-Moore字符串搜索的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。