BF算法和KMP算法

串的模式匹配算法即确定主串中所含子串第一次出现的位置。BF算法是古典的,采用穷举的思想,而KMP算法是模式匹配算法的改进算法。

1.BF算法设计思想:将主串的第pos个字符和模式的第1个字符比较, 若相等,继续逐个比较后续字符; 若不等,从主串的下一字符(pos+1)起,

重新与第一个 字符比较。直到主串的一个连续子串字符序列与模式相等 。返回值为S中与T匹配的子序列第一个字符的序号,即匹配成功。 否则,匹配失

败。

例子:主串s="ababcabcacbab",模式t="abcac"

BF算法的思想很简单,下边看一下实现:

1.简单的算法

 1 public class StringUtil {
 2
 3      public static int index(String s1, String s2){
 4          char[] c1 = s1.toCharArray();
 5          char[] c2 = s2.toCharArray();
 6          int i=1;      //表示从第一个位置开始匹配
 7          int j=1;
 8          while(i<=c1.length&& j<=c2.length){
 9            if(c1[i-1]==c2[j-1]){    //下标从0开始
10                 i++;
11                 j++;
12               }
13               else{
14                   i=i-j+2;      //相当于向右移动一个字符的位置
15                   j=1;          //子串j回到首位,重新开始匹配
16               }
17             }
18         return i-c2.length;    //返回匹配成功的首字母位置
19     }
20  }

这种算法的时间复杂度,用n和m分别表示主串和模式串的长度,有的情况下是O(n+m);但最坏的情况下的时间复杂度O(n*m);

2,KMP算法

2.1KMP算法的设计思想

kmp算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法),算法的

思想相比传统的BF算法有点复杂,用了很长时间才理解清楚,有趣的是看到调侃BF和KMP分别解释成“Boyfriend”和“看毛片”,玩笑归玩笑,无巧不成书啊。

思想:能否利用已经部分匹配的结果而加快模式串的滑动速度? 能!而且主串S的指针i不必回溯!可提速到O(n+m)!

下图是一个简单的例子

从上面的例子中可以看到 i 值不会减小,所以只用考虑 j 的值了,那么需要思考下面两个问题:

1.  如何“记忆”部分匹配结果?

2.  如何由“记忆”结果计算出主串S第i个字符应该与模式T中哪个字符再比较?即确定模式T中的新比较起点k

由上图看到模式串 T 与 主串 S 匹配时在 i = 3出失配,然后i不回朔然后 T 串向右移动到i=3处,j 由3变为1,然后又在在i=7处失配,

继续右移,此时j(k位置)由5变成2,

i

S=‘a b a b c a b c a c b a b’           设目前应于T的第k个字符进行比较,则T的1~k-1位=S前 i-(k-1)~ i-1位

T=‘a b c a c’

k

___________________________________

i

S=‘a b a b c a b c a c b a b’

T=‘a b c a c’                         刚才肯定是在S的i处和T的第j字符 处失配,则S前i-(k-1)~i-1位=T的j-(k-1)~j-1位

k

两式联立可得:‘T1…Tk-1’=‘Tj-(k-1) …Tj-1’.

把T中各个位置的j的之变化定义为一个next数组,一旦失配,应从模式串T中第next[ j ]个字符开始与S的失配点i 重新匹配!

怎样计算模式T所有可能的失配点 j 所对应的 next[j]

例: 模 式 串 T:‘ a b a a b c a c ’

可能失配位 j: 1 2 3 4 5 6 7 8

新匹配位 next[j] :  0 1 1 2 2 3 1 2

j=1时, next[ j ]≡ 0;因为属于“j=1”;

j=2时, next[ j ]≡ 1;(由 1 到 j-1 只有 一个字符)因为属于“其他情况”;

j=3时, 由 1 到 j-1的字符串只有‘ab’,属于其他情况

j=4时,由 1 到 j-1,‘aba‘看到 T1 = T3(即a) k=2 即属于第二种情况,next[j]=2,

j=5时,由1到j-1,‘abaa’ T1=T4同上 k=2,

......

对上边的传统算法的图用KMP算法改进如下:

算法实现:

 1  public static int IndexKMP(String S,String T){
 2
 3        int i=0; int j=-1;
 4        int[] next=getNext(T);
 5
 6        while(i<S.length()&&j<T.length()){
 7
 8           if(j==-1||S.charAt(i)==T.charAt(j)){
 9               i++;
10               j++;
11           }
12           else {
13               j=next[j];
14           }
15      }
16      if(j==T.length()){   //下标从0开始,+1这里返回的是位置
17          return i-j+1; }
18        return -1;
19    }

得到next数组的方法

 1 public static int[] getNext(String T){
 2        int j=-1;
 3        int i=0;
 4        int next[]=new int[T.length()+1];
 5         next[0]=-1;
 6        while(i<T.length()){
 7            if(j==-1||T.charAt(i)==T.charAt(j)){
 8                j++;
 9                i++;
10                next[i]=j;
11            } else {
12                j=next[j];
13         }
14        }
15        return next;
16    }

KMP算法的时间复杂度:由于指针i无须回溯,比较次数仅为n,即使加上计算next[j]时所用的比较次数m,比较总次数也仅为n+m=O(n+m),大大快于BF算法。

时间: 2024-10-09 11:58:52

BF算法和KMP算法的相关文章

字符串匹配的BF算法和KMP算法学习

引言:关于字符串 字符串(string):是由0或多个字符组成的有限序列.一般写作`s = "123456..."`.s这里是主串,其中的一部分就是子串. 其实,对于字符串大小关系不如是否相同重要.包括密码验证.hash列等. 而字符串的存储结构有两种:顺序存储结构和链式存储结构.由于不同的字符是连在一起的,所以一般是开足够大的空间进行顺序存储,这样更符合字符串的意义. 一.BF算法实现 一种暴力的.朴素的模式匹配算法,是的,时间复杂度为O(M*N).而下面的KMP算法则是O(M+N)

串匹配模式中的BF算法和KMP算法

考研的专业课以及找工作的笔试题,对于串匹配模式都会有一定的考察,写这篇博客的目的在于进行知识的回顾与复习,方便遇见类似的题目不会纠结太多. 传统的BF算法 传统算法讲的是串与串依次一对一的比较,举例设目标串S="ababcabcacb",模式串T="abcac",利用BF算法这个过程就会表示为: 将S串理解为数组,底标从0开始,即从a开始,第一次匹配过程如下: ok,当发现T串尚未匹配结束,就开始出现了错误,S串坐标右移+1,开始从b匹配,过程如下: 出现不同,继续

串的模式匹配算法(BF算法和KMP算法)

串的模式匹配算法 子串的定位操作通常称为串的 模式匹配,其中T称为 模式串. 一般的求子串位置的定位函数(Brute Force) 我写java的代码是这样的 int index(String S,String T,int pos){ char[] s_arr = S.toCharArray(); char[] t_arr = T.toCharArray(); int i,j,k;//i是主串S的指针,j是模式串的指针 if(pos < 0 || pos>S.length() || S.len

BF算法和KMP算法(javascript版本)

var str="abcbababcbababcbababcabcbaba";//主串 var ts="bcabcbaba";//子串 function BF(s,t){//BF算法 var i=0,j=0,v=-1; while(i<s.length&&j<t.length){ if(s[i]==t[j]){//相等就移动指针 i++; j++; } else{//指针归零 i=i-j+1; j=0; } } if(j==t.lengt

字符串的模式匹配——Brute-Force算法和KMP算法

子串的定位操作是要在主串S中找出一个与子串T相同的子串,通常把主串S称为目标,把子串T称为模式把从目标S中查找模式为T的子串的过程称为“模式匹配”. 1.Brute-Force算法的设计思想 Brute-Force是普通的模式匹配算法.将主串S的第1个字符和模式T的第1个字符比较,若相等,继续逐个比较后续字符:若不等,从主串的下一字符起,重新与模式的第一个字符比较,直到主串的一个连续子串字符序列与模式相等 ,返回值为S中与T匹配的子序列第一个字符的序号,即匹配成功:否则,匹配失败,返回值 0.

字符串匹配的算法(暴力算法和KMP算法)

学习字符串匹配算法有一段时间了,不过还是有点迷糊,虽然了解算法过程,但是在编码的时候还是会有些迷糊. 先把写的程序放在这里,以后有时间再来翻着看看吧! #include<iostream> #include<string> using namespace std; int KMPfind(char* s, char* p); void GetNext(char* p, int next[]); int ViolentMatch(char* s, char* p); int main

时空权衡之输入增强 ----字符串匹配算法Horspool算法和Boyer-Moore算法

在算法设计的时空权衡设计技术中,对问题的部分或者全部输入做预处理,对获得的额外信息进行存储,以加速后面问题的求解的思想,我们称作输入增强. 其中字符串匹配算法Horspool算法和Boyer-Moore算法就是输入增强的例子. 首先了解一下字符串匹配的概念.我们把在一个较长的n个字符的串中,寻找一个给定的m个字符的串的问题,称为字符串匹配问题.较长的串称为text,而需要寻找的串称为pattern. 字符串匹配问题的蛮力算法很好理解:我们把pattern与text第一个字符对齐,从左往右比较pa

使用Apriori算法和FP-growth算法进行关联分析(Python版)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹