BWT

KMP

Boyer-Moore


BWT

[IR] BWT+MTF+AC 中已经介绍了BWT (Burrows–Wheeler_transform)数据转换算法,

这种变换方式不仅方便压缩,同时对pattern search也带来了意想不到的好处。

事实上,BWT形式的数据,可以仅还原局部数据,而非必须还原完整的文件。

Left

Symbol #Less Than
A 0
B 3
N 4
[ 6
] 7

Right

Position Symbol #Matching(idx)
B   +->:[  0
N +->:A 0
N +->:A 1
[ E 0
A +->:B 0
A +->:N 1
] :A 0
A +->:N 2

图示化以上搜索过程(其中一步Postion:5):

匹配的过程,实际就是搜索范围逐渐缩小的过程,如下:

若能持续搜索到Pattern最后一个字符,则说明该字符串(pattern)在文本中。

时间复杂度就是O(len(pattern))


Knuth-Morris-Pratt (KMP)

因为brute Force太蠢,所以有了该算法。

• Brute force pattern matching runs in time O(mn) in the worst case.
• But most searches of ordinary text take O(m+n), which is very quick.

那么,剩下的唯一问题就是,如何构造《部分匹配表》(Partial Match Table)

P[j]: The largest prefix of P[0 .. j-1] that is a suffix of P[1 .. j-1].

"部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABACAB"为例,

[0] ABACAB- P[0 .. -1]的前缀和P[1 .. -1]的后缀为“非法”,共有元素的长度为-1;

[1] ABACAB- P[0 .. 0]的前缀和P[1 .. 0]的后缀为空,共有元素的长度为0;

[2] ABACAB- P[0 .. 1]的前缀为{A},P[1 .. 1]的后缀为空,共有元素的长度为0;

[3] ABACAB- P[0 .. 2]的前缀为{A, AB},P[1 .. 2]的后缀为{A},共有元素的长度为1;

[4] ABACAB- P[0 .. 3]的前缀为{A, AB, ABA},P[1 .. 3]的后缀为{AC, C},共有元素的长度为0;

[5] ABACAB- P[0 .. 4]的前缀为{A, AB, ABA, ABAC},P[1 .. 4]的后缀为{ACA, CA, A},共有元素的长度为1;

但,也有缺陷:

KMP doesn’t work so well as the size of the alphabet increases
– more chance of a mismatch (more possible mismatches)
– mismatches tend to occur early in the pattern, but KMP is faster when the mismatches occur later


Boyer-Moore Algorithm

算是一种改进形式,跟重视后缀;头部对齐,从尾部比较。

Most text processors use BM for “find” (&“replace”) due to its good performance for general text documents.

Ref: 字符串匹配的Boyer-Moore算法

Link: http://www.cs.utexas.edu/users/moore/publications/fstrpos.pdf

特点:《好字符规则》和《坏字符规则》,以最大移动值为准。

一个简单的示例:

Step 1

首先,"字符串"与"搜索词"头部对齐,从尾部开始比较。

这是一个很聪明的想法,因为如果尾部字符不匹配,那么只要一次比较,就可以知道前7个字符(整体上)肯定不是要找的结果。

我们看到,"S"与"E"不匹配。这时,"S"就被称为"坏字符"(bad character),即不匹配的字符。

我们还发现,"S"不包含在搜索词"EXAMPLE"之中,这意味着可以把搜索词直接移到"S"的后一位。如下:

Step 2

依然从尾部开始比较,发现"P"与"E"不匹配,所以"P"是"坏字符"。

但是,"P"包含在搜索词"EXAMPLE"之中。所以,将搜索词后移两位,两个"P"对齐。(利用了pattern内部的信息)

这个两位是怎么来的呢?

Ans:《坏字符规则》

后移位数 = 坏字符的位置 - 搜索词中的上一次出现位置

OK,根据这个规则,再重新审视Step1 and Step2。

Step 1: 后移位数=6-(-1)=7  // -1:在pattern中未发现坏字符

Step 2: 后移位数=6-4=2     //  4:在pattern中idx=4发现坏字符

However,这样是不够的,在某种情况下还不能达到更优的移动策略。

继续我们的示例:

Step 1

依然从尾部开始比较,"E"与"E"匹配;接下来,匹配了更多。

比较前面一位,"MPLE"与"MPLE"匹配。我们把这种情况称为"好后缀"(good suffix),即所有尾部匹配的字符串。

注意,"MPLE"、"PLE"、"LE"、"E"都是好后缀。

但接下来,继续比较前一位,发现"I"与"A"不匹配。所以,"I"是"坏字符"。

根据"坏字符规则",此时搜索词应该后移 2 - (-1)= 3 位。如下:

但,看上去这个move不是很聪明的样子,显然可以一次性移动更多步。

初步看上去,并没有利用到Pattern中两次出现的E。

如何利用?

Ans:《好后缀规则》

后移位数 = 好后缀的位置 - Pattern中的上一次出现位置

OK,根据这个规则,再重新审视Step1。

Step 1: 后移位数=6-=6  // 0:"好后缀"(MPLE、PLE、LE、E)之中[Ref:KMP"部分匹配表"],只有"E"在"EXAMPLE"出现在头部,idx=0

  1. "好后缀"的位置以最后一个字符为准。假定"ABCDEF"的"EF"是好后缀,则它的位置以"F"为准,即5(从0开始计算)。
  2. 如果"好后缀"在搜索词中只出现一次,则它的上一次出现位置为 -1。也就是pattern靠前的位置没有再出现了呢。
  3. 如果"好后缀"有多个
    1. 最长的那个"好后缀",位置灵活;考前位置出现的话,优先选!否则,查看其他“好后缀”。
    2. 其他"好后缀",上一次出现位置必须在头部。

比如,假定"BABCDAB"的"好后缀"是"DAB"、"AB"、"B",这时"好后缀"的上一次出现位置是什么?

BABCDAB

BABCDAB

BABCDAB  <----

回答是,此时采用的好后缀是"B",它的上一次出现位置是头部,即第0位。

这个规则也可以这样表达:如果最长的那个"好后缀"只出现一次,则可以把搜索词改写成如下形式进行位置计算"(DA)BABCDAB",即虚拟加入最前面的"DA"。

更巧妙的是,这两个规则的移动位数,只与搜索词有关,与原字符串无关。因此,可以预先计算生成《坏字符规则表》和《好后缀规则表》。使用时,只要查表比较一下就可以了。

那么,如何事前制表?

Ref: http://www.cs.utexas.edu/users/moore/publications/fstrpos.pdf

[IR] String Matching的更多相关文章

  1. Binary String Matching

    问题 B: Binary String Matching 时间限制: 3 Sec  内存限制: 128 MB提交: 4  解决: 2[提交][状态][讨论版] 题目描述 Given two strin ...

  2. NYOJ之Binary String Matching

    Binary String Matching 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述     Given two strings A and B, whose a ...

  3. ACM Binary String Matching

    Binary String Matching 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 Given two strings A and B, whose alp ...

  4. 南阳OJ----Binary String Matching

    Binary String Matching 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 Given two strings A and B, whose alp ...

  5. Binary String Matching(kmp+str)

    Binary String Matching 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 Given two strings A and B, whose alp ...

  6. Aho - Corasick string matching algorithm

    Aho - Corasick string matching algorithm 俗称:多模式匹配算法,它是对 Knuth - Morris - pratt algorithm (单模式匹配算法) 形 ...

  7. [POJ] String Matching

    String Matching Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4074   Accepted: 2077 D ...

  8. String Matching Content Length

    hihocoder #1059 :String Matching Content Length 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 We define the ...

  9. NYOJ 5 Binary String Matching

    Binary String Matching 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 Given two strings A and B, whose alp ...

随机推荐

  1. redis object 对象系统

    redis object对象系统 概述 redis 当中, sds字符串, adlist双向链表, dict字典, ziplist压缩链表, intset整数集合等均为底层数据结构 redis 并没有 ...

  2. 实时监听input标签输入 实时监听文本框输入 避免中文输入法无法触发onkeyup事件的问题

    前言: 对于实时监听输入,这种需求大多数都是用于一个联想字提醒,智能提醒.大家都知道onkeydown,onkeypress,onkeyup的在监听中文输入法或者右键粘贴的时候都存在一些弊端,不是那么 ...

  3. vue.js2.0新手笔记(一)——安装

    知道vue很长时间了,一直只是了解,没有深入学习,也没做什么具体的东西.现在有时间了,决定重头好好学一下,就从安装开始吧. 一.安装node vue是用npm安装,npm是node的一个包管理工具,所 ...

  4. 防止微信浏览器video标签全屏的问题

    在微信浏览器里面使用video标签,会自动变成全屏,改成下面就好了,起码可以在video标签之上加入其他元素. <video id="videoID" webkit-play ...

  5. 【响应式】foundation栅格布局的“尝鲜”与“填坑”

      提到响应式,就不得不提两个响应式框架--bootstrap和foundation.在标题上我已经说明白啦,今天给大家介绍的是foundation框架. 何为"尝鲜"?就是带大伙 ...

  6. grunt轻松入门

    项目目录,js源文件 gruntest Gruntfile.js package.json -- js ext community_plugin.js glogin_frm_cover.js iLog ...

  7. 当谈 SQL 优化时谈些什么?

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:孙银行 背景 Mysql数据库作为数据持久化的存储系统,在实际业务中应用广泛.在应用也经常会因为SQL遇 ...

  8. ESXi5.0误删除虚拟机还有办法恢复吗?答案是可以!

    [数据恢复故障描述]故障的虚拟化系统是 ESXi5.0,连接了多个LUN,其中一个1T的LUN上跑有7 台虚拟机,均为Windows Server 2003,管理员因为其它原因误删除了一台虚拟机,此台 ...

  9. struts2标签库----控制标签详解

         前面几篇文章我们介绍了有关struts2的基本内容,简单理解了整个框架的运作流程.从本篇开始我们逐渐了解和使用struts2为我们提供的标签库技术,使用这些标签可以大大降低我们表现层的开发难 ...

  10. haproxy安装配置for mysql负载均衡(ubantu)

    1.安装pcre apt-get update (apt-get install openssl libssl-dev  ==>可能需要安装的依赖包) apt-get install libpc ...