【问题标题】:String similarity: how exactly does Bitap work?字符串相似性:Bitap 究竟是如何工作的?
【发布时间】:2012-07-03 19:38:03
【问题描述】:

我正试图围绕 Bitap 算法展开思考,但无法理解算法步骤背后的原因。

我理解了算法的基本前提,即(如果我错了,请纠正我):

Two strings:     PATTERN (the desired string)
                 TEXT (the String to be perused for the presence of PATTERN)

Two indices:     i (currently processing index in PATTERN), 1 <= i < PATTERN.SIZE
                 j (arbitrary index in TEXT)

Match state S(x): S(PATTERN(i)) = S(PATTERN(i-1)) && PATTERN[i] == TEXT[j], S(0) = 1

在英文术语中,PATTERN.substring(0,i) 匹配 TEXT 的子字符串,前提是前面的子字符串 PATTERN.substring(0, i-1) 匹配成功并且PATTERN[i] 处的字符与TEXT[j] 处的字符相同。

我不明白的是这个的位移实现。 The official paper detailing this algorithm basically lays it out,但我似乎无法想象应该发生什么。 算法规范只是论文的前 2 页,但我会强调重要的部分:

这是概念的位移版本:

这里是示例搜索字符串的 T[text]:

这里是算法的痕迹。

具体来说,我不明白 T 表的含义,以及 OR 以当前状态在其中输入条目的原因。

如果有人能帮助我了解到底发生了什么,我将不胜感激

【问题讨论】:

    标签: algorithm bit-manipulation similarity


    【解决方案1】:

    T 有点令人困惑,因为您通常会在 图案从左到右:

    0 1 2 3 4
    a b a b c
    

    ...而位通常从右到左编号。

    但是写 位上方的图案向后清晰:

    位:4 3 2 1 0 c b a b a T[a] = 1 1 0 1 0 c b a b a T[b] = 1 0 1 0 1 c b a b a T[c] = 0 1 1 1 1 c b a b a T[d] = 1 1 1 1 1

    如果x 出现在位置n,则T[x] 的位n 为0,否则为1。

    等效地,您可以将其视为说,如果当前字符 在输入字符串中是x,并且您在T[x] 的位置n 中看到0,那么您 如果匹配开始 n 个字符,则只能匹配模式 以前。


    现在到匹配过程。状态的位 n 中的0 表示我们开始匹配模式 n 个字符之前(其中 0 是当前字符)。最初,没有任何匹配项。

      [start]
    1 1 1 1 1
    

    当我们消耗试图匹配的字符时,状态向左移动(在 到底部位,位 0) 并与当前字符的表条目进行或运算。第一个字符是a;在T[a] 中左移和 OR-ing 给出:

            a
    1 1 1 1 0
    

    被移入的0 位被保留,因为a 的当前字符可以 开始匹配模式。对于任何其他字符,该位将被设置为 1.

    状态的第 0 位现在是 0 的事实意味着我们开始匹配模式 当前字符;继续,我们得到:

          a b
    1 1 1 0 1
    

    ...因为 0 位已向左移动 - 认为它是说我们在 1 个字符之前开始匹配模式 - 并且 T[b] 在同一位置有一个 0,告诉 如果我们开始匹配 1 个字符,我们认为在当前位置看到 b 很好 以前。

        a b d
    1 1 1 1 1
    

    d 无法匹配任何地方;所有位都设置回1。

      a b d a
    1 1 1 1 0
    

    和以前一样。

    a b d a b
    1 1 1 0 1
    

    和以前一样。

    b d a b a
    1 1 0 1 0
    

    a 很好,如果匹配开始于 2 个字符之前或当前字符。

    d a b a b
    1 0 1 0 1
    

    b 很好,如果匹配在 1 或 3 个字符前开始。第 3 位中的 0 表示 我们几乎匹配了整个模式...

    a b a b a
    1 1 0 1 0
    

    ...但是下一个字符是a,如果匹配从 4 个字符开始就不好了 前。但是,较短的匹配可能仍然是好的。

    b a b a b
    1 0 1 0 1
    

    看起来还是不错的。

    a b a b c
    0 1 1 1 1
    

    最后,c 如果匹配在 4 个字符之前开始,则很好。事实是 0 一直到最高位意味着我们有一个匹配项。

    【讨论】:

    • 很抱歉提出这么老的问题,但是您将如何扩展此算法以便它可以处理错误搜索?
    • @DavidS diff_match_patch 有一个具有容错性的 bitap 实现。
    【解决方案2】:

    很抱歉不允许其他人回答,但我很确定我现在已经想通了。

    探索算法的基本概念是以二进制表示匹配状态(在原始帖子中定义)。原帖中的文章正式解释了它;我会试着口语化地这样做:

    让我们拥有STR,这是一个使用给定字母表中的字符创建的字符串。

    让我们用一组二进制数字表示STR:STR_BINARY。该算法要求这种表示是向后的(因此,第一个字母对应最后一个数字,第二个字母对应倒数第二个数字,等等)。

    假设RANDOM 指的是一个字符串,其中包含来自相同字母STR 的随机字符。

    在STR_BINARY 中,给定索引处的0 表示RANDOM 匹配STR 从STR[0] 到

    STR[(index of letter in STR that the 0 in STR_BINARY corresponds to)]。空格算作匹配。 1 表示RANDOM 在相同的边界内与STR 不匹配。

    一旦理解了这一点,算法就会变得更容易学习。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 2021-08-15
      • 2012-06-08
      • 2011-10-11
      • 2013-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多