【算法总结】-字符串匹配技术(二)

上篇主要讲述了蛮力法和Horspool两种字符串匹配的方式,本篇则继续总结BM和KMP两种算法实现。

三、BM算法

       *BM算法全称Boyer-Moore,它是由Bob Boyer和J Strother Moore设计于1977年。它是一种非常高校的字符串搜索算法。
       *不同于朴素模式的逐个字符比较,BM充分使用预处理P的信息来尽可能跳过更多的字符。

预处理方式

  • 坏字符(Bad Character Heuristic):当文本T中的某个字符与模式P中的某个字符不匹配时,称此失配字符为坏字符。
  • 好后缀(Good Suffix Heuristic):当文本 T 中的某个字符跟模式 P 的某个字符不匹配时,我们称文本 T 中的已经匹配的字符串为好后缀。

步骤

前提理解:对于坏字符而言,其实就是Horspool的匹配模式;但是若存在好后缀,那么我们就可以针对单一的坏字符进行优化,使其跳过更多的无用字符,提高效率。

  • 按照给定的模式及其给定的字母表,制定坏符号移动表
  • 根据坏符号移动表,辅助制定好后缀移动表
  • 设d1为坏字符移动字符个数;d1=max{length-k,1};d2为好后缀移动字符个数;
    L=max{d1,d2}
    d={d1,k=0L,k>0 d = \begin{cases} d1, & k=0 \\ L,& k>0 \end{cases}

举例

B E S S _ K N E W _ A B O U T _ B A O B A B S

待比较的字符为:BAOBAB
对于坏字符的移动表:

  • A移动1位;
  • B移动2位;
  • O移动3位;
  • 其它 移动6位;
    对于好后缀的移动表有两条规格:
    前提:k为包含的匹配好的字符个数;S为匹配的字符串(S可能是一个字符串,也可能包含多个);length为待比较的pattern字符个数
  • 若K=1;则移动个数为上一个该字符到末尾的字符个数;
  • K>1{S,lengthknSpattern(length1),lengthknSSlength,lengthknSS K>1 \begin{cases} 移动个数为S的最后一个字符到末尾的字符个数, & length-k的前n个字符中,依旧包含S \\ 移动个数为pattern第一个字符到末尾的字符个数(length-1) ,& length-k的前n个字符中,不包含S,但是首字母为S的最后最后一个字符\\ 移动个数为length,&length-k的前n个字符中,不包含S,且首字母不是S的最后一个字符 \end{cases}
    举例说明:
    BAOBAB中,若好后缀为B,则移动2位;若好后缀为AB,BAB或者OBAB,只要K<length,则移动最开始B到末尾的字符串个数,即为5;

如下我们则根据
d={d1,k=0L,k&gt;0 d = \begin{cases} d1, &amp; k=0 \\ L,&amp; k&gt;0 \end{cases}
来举例说明:
DEMO1:其中pattern为BAOBAB,length=6

K!=B,且pattern不包含K;
k=0,d=d1=length-0=6,移动6位
B E S S _ K N E W _ A B O U T _ B A O B A B S
B A O B A B
B A O B A B
B==B,A==A,k=2,S为{A,B},pattern不包含S,但是首字母为B
d=L;d1=length-k=4;d2=5; 所以d=max{d1,d2}=5
B E S S _ K N E W _ A B O U T _ B A O B A B S
B A O B A B
B A O B A B
B A O B A B
B==B,_!=A,k=1
d=L;d1=length-1=5;d2=2;所以d=max{d1,d2}=5
B E S S _ K N E W _ A B O U T _ B A O B A B S
B A O B A B
B A O B A B
B A O B A B
B A O B A B

找到了匹配的字符串位置。
DEMO2:其中pattern为CAOPAB,length=6

K!=B,且pattern不包含K
k=0,d=d1=length-0=6,移动6位
B E S S _ K N E W _ A B O U T _ C A O B A B S
C A O B A B
C A O B A B
B==B,A==A ,S为{A,B},但是pattern中不包含S,且首字符不是S的最后一个字符
d2=6(移动length),d1=length-2=4,所以d=d2=6
B E S S _ K N E W _ A B O U T _ C A O B A B S
C A O B A B
C A O B A B
C A O B A B
A!=B,则k=0,因为pattern中包含A,所以移动A的距离
d=d1=A的移动距离=1
B E S S _ K N E W _ A B O U T _ C A O B A B S
C A O B A B
C A O B A B
C A O B A B
C A O B A B
O!=B,则k=0;因为pattern中包含O,所以移动O的距离
d=d1=O的移动距离=3
B E S S _ K N E W _ A B O U T _ C A O B A B S
C A O B A B
C A O B A B
C A O B A B
C A O B A B
C A O B A B

总结

对于坏字符原则,其实就是Horspool算法的方式应用。当匹配为0的时候,我们直接采用坏字符的匹配规则;当匹配大于0的时候,我们则需要判定坏字符和好后缀的值,采取最大值。

四、KMP算法

       KMP算法,全称为Knuth-Morris-Pratt 字符串查找算法,其实这也是高德纳在写书的遇到排版问题的时候抱怨进而研究了这个算法,所以其实KMP算法也是三个人名字的首字母缩写,其中M和P是他的两个学生。
上一个BM算法的好后缀的处理方式其实和KMP是雷同的,只不过BM采用的后缀原则,而KMP采用的前缀原则。

步骤

举例

总结

五、总结

posted on 2018-12-23 16:16  huohuoL  阅读(216)  评论(0编辑  收藏  举报

导航