查找字符串中搜索词的所有索引

2023-12-12

我需要一种快速方法来查找字符串中可能出现的搜索词的所有索引。我尝试过这种“蛮力”String扩展方法:

// Note: makes use of ExSwift
extension String
{
    var length: Int { return count(self) }

    func indicesOf(searchTerm:String) -> [Int] {
        var indices = [Int]()
        for i in 0 ..< self.length {
            let segment = self[i ... (i + searchTerm.length - 1)]
            if (segment == searchTerm) {
                indices.append(i)
            }
        }
        return indices;
    }
}

...但是它的速度慢得离谱,尤其是搜索词越短。快速找到所有索引的更好方法是什么?


正如马丁所说,您可以在字符串匹配中实现一些众所周知的最快算法,高德纳-莫里斯-普拉特字符串搜索算法(或KMP算法)搜索“单词”的出现W在主“文本字符串”内S.

算法有复杂度O(n), where n的长度是SO is 大 O 表示法.

extension String {

    // Build pi function of prefixes
    private func build_pi(str: String) -> [Int] {

       var n = count(str)
       var pi = Array(count: n + 1, repeatedValue: 0)
       var k = -1
       pi[0] = -1

       for (var i = 0; i < n; ++i) {
           while (k >= 0 && str[k] != str[i]) {
              k = pi[k]
           }
           pi[i + 1] = ++k
       }

       return pi
    }

    // Knuth-Morris Pratt algorithm
    func searchPattern(pattern: String) -> [Int] {

       var matches = [Int]()
       var n = count(self)

       var m = count(pattern)
       var k = 0
       var pi = build_pi(pattern)

       for var i = 0; i < n; ++i {
           while (k >= 0 && (k == m || pattern[k] != self[i])) {
              k = pi[k]
           }
           if ++k == m {
              matches.append(i - m + 1)
           }
       }

       return matches
    }

    subscript (i: Int) -> Character {
        return self[advance(self.startIndex, i)]
    }
}

然后您可以通过以下方式使用它:

var string = "apurba mandal loves ayoshi loves"
var pattern = "loves"

println(string.searchPattern(pattern))

输出应该是:

[14, 27]

它属于字符串内模式出现的起始索引。我希望这对你有帮助。

EDIT:

正如马丁在他的评论中所说,你需要避免使用advance索引函数String by an Int因为它是O(到索引的位置).

一种可能的解决方案是将String到一个数组Character然后访问索引是O(1).

然后extension可以改成这个:

extension String {

   // Build pi function of prefixes
   private func build_pi(str: [Character]) -> [Int] {

      var n = count(str)
      var pi = Array(count: n + 1, repeatedValue: 0)
      var k = -1
      pi[0] = -1

      for (var i = 0; i < n; ++i) {
          while (k >= 0 && str[k] != str[i]) {
              k = pi[k]
          }
          pi[i + 1] = ++k
      }

      return pi
   }

   // Knuth-Morris Pratt algorithm
   func searchPattern(pattern: String) -> [Int] {

      // Convert to Character array to index in O(1)
      var patt = Array(pattern)
      var S = Array(self)

      var matches = [Int]()
      var n = count(self)

      var m = count(pattern)
      var k = 0
      var pi = build_pi(patt)

      for var i = 0; i < n; ++i {
         while (k >= 0 && (k == m || patt[k] != S[i])) {
             k = pi[k]
         }
         if ++k == m {
             matches.append(i - m + 1)
         }
      }

      return matches
   }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查找字符串中搜索词的所有索引 的相关文章

随机推荐

  • 在 Javascript 中将字符串添加到数字

    我有功能addNumber如果我单击具有特定值的按钮 该值将连接到变量 b 但如果 a 的值不是数字 则该函数不起作用 我缺少什么 我认为该函数使用参数 a 就像它是一个字符串一样 否则 数字就会被累加起来 因此 如果b 0 a x 的结果
  • 已安装的软件包在 Google Cloud Shell 中消失

    我尝试在 Google Cloud Platform Console 中安装一堆 python 包 但磁盘空间不足 安装失败 有趣的是 在某些时候 网络连接丢失了 我应该重新连接它 然后我检查了一些在尝试安装其他 python 软件包之前已
  • 从 Python 运行 bash 脚本

    我需要从 Python 运行 bash 脚本 我让它按如下方式工作 import os os system xterm hold e scipt sh 这不完全是我正在做的事情 但几乎是我的想法 工作正常 打开一个新的终端窗口 我将其保留用
  • 合并具有多个匹配项的数据框时仅选择第一行

    我有两个数据框 数据 和 分数 并想将它们合并到 id 列上 data data frame id c 1 2 3 4 5 state c KS MN AL FL CA scores data frame id c 1 1 1 2 2 3
  • JavaScript 错误:“不是函数”

    看起来 smth 不是函数 是 JavaScript 中一个非常常见的问题 但是在查看了相当多的线程之后 我仍然无法理解在我的情况下是什么导致了它 我有一个自定义对象 定义为 function Scorm API 12 var Initia
  • phpunit 中未定义的 action()

  • 何时使用 std::begin 和 std::end 而不是容器特定版本[重复]

    这个问题在这里已经有答案了 是否有任何一般偏好或规则来解释何时应使用容器特定版本的 begin 和 end 而不是自由函数std begin and std end 据我了解 如果函数是模板 其中容器类型是模板参数 那么std begin
  • 绑定 odeint 变量

    我正在使用 odeint 来模拟一个系统 其中有几个变量不应小于零 是否有适当的方法将 odeint 中的变量绑定到特定范围 在odeint中不存在这种可能性 我想没有算法可以做到这一点 您必须以某种方式对 ODE 中的界限进行编码 如果您
  • excel超链接什么都没有

    我有很多超链接 我想为每个超链接分配一个宏 并且 Worksheet FollowHyperlink 仅捕获插入的超链接 但不捕获 HYPERLINK 函数 所以我希望我插入的超链接不引用任何内容 这样当我按下它们时什么也不会发生 或者我希
  • 如何在 Flask-RESTful 中添加自定义 HTTP 响应头?

    我正在使用 Flask RESTful 并且希望通过向我的响应添加自定义 HTTP 标头来处理某些错误 是否有标准的 Flask 或 Flask RESTful 方法可以做到这一点 结果我跳过了文档的那部分 class Todo3 Reso
  • Kendo Grid 移动到下一个单元格后不保存值

    我尝试修改kendo Grid的InCell编辑模式的行为 我的意思是我尝试使用箭头导航到单元格 但这样做时遇到问题 这是我的代码 grid keydown function e debugger isEditStarted true va
  • 在地图上绘制绕纬度/经度的时间半径

    我正在与gmapsdistanceR 中的包 我有我的 API 密钥 并且我熟悉包中的功能 然而 我想从相反的方向解决一个问题 而不是仅仅找到Time Distance and Status纬度 经度之间是纬度 经度的向量 我想输入一个纬度
  • x86 函数调用类型

    我是x86新手 我的问题是关于函数调用 据我所知 有三种函数调用类型 短调用 0xe8 远调用 0x9a 和近调用 0x 有些将短调用称为相对调用 ip arg cs inv 将远调用称为绝对调用 ip arg cs arg 但近调用又如何
  • 如何使用外部库 JAR 在终端中运行 Java 程序

    这应该很简单 但我以前从未这样做过 也没有找到任何解决方案 我目前正在使用 Eclipse 来编写我的程序 它导入一些外部 JAR 库 例如 google data api 库 我可以使用 Eclipse 来编译 构建 运行该程序 但现在我
  • 在表中打印查询结果

    如果我有一个名为 info 的 MySQL 表 如下所述 并且我想打印出一个 HTML 表 如下所述 我该怎么做 MySQL表中的字段 id subject category actions date status HTML 表格结构 两列
  • 从生成的表中检索数据时对象名称“dbo.TableName”无效

    我首先使用实体 框架代码来创建我的表 请注意 创建表 而不是数据库 因为我正在托管环境中工作 并且没有允许创建数据库的用户 提交数据库更新工作正常 但检索数据会出现异常 异常详细信息 System Data SqlClient SqlExc
  • 无法使用 SMO 枚举 SQL Server 2008 注册服务器

    我的工作站上安装了 SQL Server 2005 Management Studio 此后我安装了 SQL Server 2008 工作站工具并删除了 SQL Server 2005 工具 我现在正在编写一个 C 程序 它会迭代我在 Ma
  • Javascript removeEventListener 不起作用 - 事件侦听器仍然存在

    我已经研究了一些解决这个问题的方法 但我不能真正告诉 我的代码是 lb document body if lb addEventListener lb addEventListener keyup function event keyPre
  • 在文本后添加格式化符号,保留预先存在的文本的字符格式

    我想在单元格中的现有文本后插入红色勾号 或向下箭头 如何插入字符和retain单元格中预先存在的字符格式 我只对这些单元格内的一些单词进行粗体 下划线或着色 通常建议的代码将原始单元格内容的所有自定义字符格式恢复为单元格字体格式 Activ
  • 查找字符串中搜索词的所有索引

    我需要一种快速方法来查找字符串中可能出现的搜索词的所有索引 我尝试过这种 蛮力 String扩展方法 Note makes use of ExSwift extension String var length Int return coun