优化编辑距离算法

2023-12-11

我有一个存储过程,它使用编辑距离来确定最接近用户键入内容的结果。唯一真正影响速度的是在选择距离最小的记录之前计算所有记录的 Levenshtein 距离的函数(我通过将 0 代替对 Levenshtein 函数的调用来验证这一点)。该表有 150 万条记录,因此即使是最轻微的调整也可能会缩短几秒钟。现在整个过程持续了10多分钟。这是我正在使用的方法:

ALTER function dbo.Levenshtein
( 
    @Source nvarchar(200), 
    @Target nvarchar(200) 
) 
RETURNS int
AS
BEGIN
DECLARE @Source_len int, @Target_len int, @i int, @j int, @Source_char nchar, @Dist int, @Dist_temp int, @Distv0 varbinary(8000), @Distv1 varbinary(8000)

SELECT @Source_len = LEN(@Source), @Target_len = LEN(@Target), @Distv1 = 0x0000, @j = 1, @i = 1, @Dist = 0

WHILE @j <= @Target_len
BEGIN
    SELECT @Distv1 = @Distv1 + CAST(@j AS binary(2)), @j = @j + 1
END

WHILE @i <= @Source_len
BEGIN
    SELECT @Source_char = SUBSTRING(@Source, @i, 1), @Dist = @i, @Distv0 = CAST(@i AS binary(2)), @j = 1

WHILE @j <= @Target_len
BEGIN
    SET @Dist = @Dist + 1
    SET @Dist_temp = CAST(SUBSTRING(@Distv1, @j+@j-1, 2) AS int) +
                  CASE WHEN @Source_char = SUBSTRING(@Target, @j, 1) THEN 0 ELSE 1 END

    IF @Dist > @Dist_temp
    BEGIN
        SET @Dist = @Dist_temp
    END

    SET @Dist_temp = CAST(SUBSTRING(@Distv1, @j+@j+1, 2) AS int)+1

    IF @Dist > @Dist_temp SET @Dist = @Dist_temp
    BEGIN
        SELECT @Distv0 = @Distv0 + CAST(@Dist AS binary(2)), @j = @j + 1
    END
END

SELECT @Distv1 = @Distv0, @i = @i + 1
END

RETURN @Dist
END

我应该从这里去哪里?


我过去这样做的方法是将“数据库”(实际上是用于拼写纠正器的单词词典)存储为特里树。

然后我使用分支定界例程来查找最近的匹配条目。对于小距离,所花费的时间与距离呈指数关系。对于长距离,它与字典的大小成线性关系,就像您现在看到的那样。

分支定界基本上是 trie 的深度优先树遍历,但有错误预算。在每个节点,您跟踪当前的编辑距离,如果超出预算,则修剪树的该分支。

首先,您以零预算进行步行。这只会找到完全匹配的结果。如果你没有找到匹配的,那么你就以 1 的预算走过去。这将在距离 1 处找到匹配项。如果找不到任何匹配项,则以预算 2 进行匹配,依此类推。这听起来效率很低,但由于每次步行比前一次花费的时间要多得多,因此时间主要由您最后一次步行决定。

添加:代码概要(请原谅我的 C):

// dumb version of trie node, indexed by letter. You can improve.
typedef struct tnodeTag {
  tnodeTag* p[128];
} tnode;

tnode* top; // the top of the trie

void walk(tnode* p, char* s, int budget){
  int i;
  if (*s == 0){
    if (p == NULL){
      // print the current trie path
    }
  }
  else if (budget >= 0){
    // try deleting this letter
    walk(p, s+1, budget-1);
    // try swapping two adjacent letters
    if (s[1]){
      swap(s[0], s[1]);
      walk(p, s, budget-1);
      swap(s[0], s[1]);
    }
    if (p){
      for (i = 0; i < 128; i++){
        // try exact match
        if (i == *s) walk(p->p[i], s+1, budget);
        // try replacing this character
        if (i != *s) walk(p->p[i], s+1, budget-1);
        // try inserting this letter
        walk(p->p[i], s, budget-1);
      }
    }
  }
}

基本上,您可以通过跳过字母并在同一节点搜索来模拟删除该字母。您可以通过降序排列 trie 而不前进 s 来模拟插入字母。您可以通过表现得好像字母匹配来模拟替换字母,即使事实并非如此。当你掌握了它的窍门后,你可以添加其他可能的不匹配,例如用 O 替换 0,用 L 或 I 替换 1 - 像这样的愚蠢的东西。

您可能想要添加一个字符数组参数来表示您在 trie 中找到的当前单词。

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

优化编辑距离算法 的相关文章

  • php 日期函数和 Carbon 哪个更快?

    Carbon 是 DateTime 的简单 PHP API 扩展 我想知道我们可以通过 Composer 安装 Carbon 来使用日期时间函数 php 日期时间函数和 Carbon 哪个更快 我对您的评论做了一些测试 比较了 DateTi
  • HTML5 - Canvas - 大图像优化

    我需要建立一个HTML5 canvas其中包含非常大的图像 可能高达 10 15MB 我的第一个想法是将图像分成几个块 这些块将在画布上水平移动时加载 对这个想法有什么想法吗 这是一件好事吗 也许我错过了一些已经实现的优化功能 你说得对 这
  • Java 反射性能

    使用反射创建对象而不是调用类构造函数是否会导致任何显着的性能差异 是的 一点没错 通过反射查找类是 按幅度 更贵 Quoting Java关于反射的文档 http java sun com docs books tutorial refle
  • 如何加速我的 Perl 程序?

    这确实是两个问题 但它们非常相似 为了简单起见 我想我应该把它们放在一起 Firstly 给定一个已建立的 Perl 项目 除了简单的代码优化之外 还有哪些不错的方法可以加速它 Secondly 用Perl从头开始编写程序时 有哪些好的方法
  • 为什么我应该使用内联代码? [复制]

    这个问题在这里已经有答案了 我是一名 C C 开发人员 这里有几个始终困扰我的问题 常规 代码和内联代码之间有很大区别吗 主要区别是什么 内联代码只是宏的一种 形式 吗 选择内联代码时必须进行什么样的权衡 Thanks 表现 正如之前的答案
  • 优化 tribool 数组的空间

    让我从一些背景开始 通过 tribool 我理解一个可以保存以下值之一的变量 true false or null 有问题复制整数数组与布尔指针数组 https stackoverflow com questions 4350041 cop
  • L-BFGS 是否有 tf.keras.optimizers 实现?

    有人有 L BFGS 算法的 Tensorflow 2 tf keras 子类吗 如果想使用 L BFGS 目前有两个 官方 选项 TF概率 SciPy 优化 这两个选项使用起来相当麻烦 尤其是在使用自定义模型时 因此 我计划实现 tf k
  • R 中的约束优化

    我正在尝试使用http rss acs unt edu Rdoc library stats html constrOptim html http rss acs unt edu Rdoc library stats html constr
  • 有没有办法让这个哈希查找更快?

    我需要 非常 快速处理有限范围的字符串 计算它们的值 输入文件的形式为 January 7 March 22 September 87 March 36 等等 因为线宽相同 所以我可以简单地读取一行fread相当快 而且我已经开发了一个完美
  • 可以通过Data.Function.fix来表达变形吗?

    我有这个可爱的fixana这里的函数执行速度比她的姐妹快 5 倍左右ana 我有一个criterion报告支持我这一点 ana alg Fix fmap ana alg alg fixana alg fix f gt Fix fmap f
  • 在调用函数两次和将返回值存储在变量中之间选择哪一个?

    我有以下场景 并且我多次遇到类似的场景 以下两个选项中哪一个更可取 选项 1 String result getDetails null getDetails 选项2 String returnValue getDetails String
  • 完全禁用 NVCC 优化

    我正在尝试测量 GPU 上的峰值单精度触发器 为此我正在修改 PTX 文件以在寄存器上执行连续的 MAD 指令 不幸的是 编译器正在删除所有代码 因为它实际上没有做任何有用的事情 因为我没有执行任何数据的加载 存储 是否有编译器标志或编译指
  • 使用 Numba 加速矢量距离计算

    以下是我为 3 D 环形几何中的距离 平方 计算编写的一些函数 用于该 3 D 空间中的粒子集合 import itertools import time import numpy as np import scipy import num
  • GCC:分段错误和调试程序仅在优化时崩溃

    这是线程的后续内容 C 分段错误 也许 GDB 在骗我 https stackoverflow com questions 22828609 c segmentation fault and maybe gdb is lying to me
  • C for 循环索引:新 CPU 中的前向索引更快吗?

    在我订阅的邮件列表上 两位知识渊博的 IMO 程序员正在讨论一些优化的代码 并说了以下内容 在 5 8 年前发布的 CPU 上 向后迭代 for 循环稍微快一些 e g for int i x 1 i gt 0 i 因为比较i归零比将其与其
  • 有效积累稀疏 scipy 矩阵的集合

    我有一个 O N NxN 的集合scipy sparse csr matrix 每个稀疏矩阵都有 N 个元素集 我想将所有这些矩阵加在一起以获得一个常规的 NxN numpy 数组 N 约为 1000 矩阵内非零元素的排列使得所得总和肯定不
  • gcc 没有小字符串优化吗?

    Most std string实现 包括 GCC 使用小字符串优化 例如 有一个answer https stackoverflow com a 21710033 2640636讨论这个 今天 我决定检查我编译的代码中的字符串在什么时候被移
  • 相当于 min() 的 rowMeans()

    我在 R 邮件列表上多次看到这个问题 但仍然找不到满意的答案 假设我有一个矩阵m m lt matrix rnorm 10000000 ncol 10 我可以通过以下方式获得每行的平均值 system time rowMeans m use
  • 调度算法,找到设定长度的所有非重叠区间

    我需要为我的管理应用程序实现一种算法 该算法将告诉我何时可以将任务分配给哪个用户 我实现了一个蛮力解决方案 它似乎有效 但我想知道是否有更有效的方法来做到这一点 为了简单起见 我重写了算法以对数字列表进行操作 而不是数据库查询等 下面我将尝
  • Java 中查看 ArrayList 是否包含对象的最有效方法

    我有一个 Java 对象的 ArrayList 这些对象有四个字段 我用其中两个字段来将对象视为与另一个对象相等 我正在寻找最有效的方法 给定这两个字段 以查看数组是否包含该对象 问题在于这些类是基于 XSD 对象生成的 因此我无法修改类本

随机推荐