字符串模式匹配算法--BF & KMP算法

一、字符串模式匹配

       设有主串s和字串t,字串t的定位就是在s中匹配到一个与字串t相等的字串。通常称主串s为目标串,字串t成为模式串,把定位过程成为模式匹配。模式匹配是一个复杂的串操作。许多人提出各种不同的算法,以BF算法和KMP算法为例。

二、BF算法(简单匹配算法)

       Brute-Force简称BF算法,亦称为简单匹配算法。i:主串指针 j:字串指针

算法效率不高:主串指针i在若干个字符序列比较相等后,若有一个字符不相等,仍需回溯

至i(i=i-j+1),最好情况下时间复杂度o(m)(主串开头即匹配到),最快情况下时间复杂度o(n*m)(主串结尾匹配)。

BF算法如下:(改进)

#define MAXSIZE 256 //BF算法,时间复杂度 最好情况o(m)(s串开头就匹配到) 最坏情况0(n*m)(s串结尾匹配到) int BF_Index(char* s, char * t) { assert(s!=NULL && t!=NULL); //断言 int i=0; int j=0; //2个回溯指针 int index= 0; int stateindex = strlen(s)-strlen(t); int len = strlen(t); while((index <= stateindex )&& (j stateindex时,s串剩余长度小于t串长度,没必要匹配了。 { if(s[i]==t[j]) { i=i+1; j=j+1; } else { i=i-j+1; index = i; j=0; } } if(j == len) { //匹配 return (i-len); //不是i-len+1 此时i也加1了 } else { return (-1); } }

 

三、KMP算法(BF改进,消除主串指针回溯)

            KMP算法是由D.E.Kunth、J.H.Morris、V.R.Pratt三人共同提出的,因此称为KMP算法。该算法对BF算法进行了较大的改进,消除了主串指针的回溯,提高了串匹配的算法效率。KMP算法的总的时间复杂度由求next数组的时间复杂度和匹配函数时间复杂度组成,为o(m+n)。

KMP算法思想:分析模式串s,求的模式串的部分匹配信息,用next数组保存。KMP算法的核心就是去next数组的值。

定义如下:
next[0]=-1;
next[i]=k最大值 (存在 0< k < i 使t[0]t[1]t[2]..t[k-1] == t[i-k]t[i-k+1]...t[i-1])
next[i]=0 其他情况
例如
               "a b c a b a a"          " a a a a b"
 next数组 -1 0 0 0 1 2 1             -1 0 1 2 3

KMP算法如下:

/* KMP算法 时间复杂度o(n+m) 重点是求t串的next[i]数组 定义如下: next[0]=-1; next[i]=k最大值 (存在 0< k < i 使t[0]t[1]t[2]..t[k-1] == t[i-k]t[i-k+1]...t[i-1]) next[i]=0 其他情况 例如 "a b c a b a a" " a a a a b" next数组 -1 0 0 0 1 2 1 -1 0 1 2 3 */ void GetNext(char* t, int* next) //这个函数求next值,难理解。画下图 { int k=-1; int i=0; int len = strlen(t); next[0] = -1; while(i=tlen) { return (i-tlen); } else { return (-1); } }

 

但是KMP算法依然存在可改进的地方,比如当主串s="aaabaaaab",字串t="aaaab"情况,KMP算法进行了多余的比较。

KMP改进算法:利用nextval数组 
          s= "a a a b a a a a b"  
          t = "a a a a b"
next        -1 0 1 2 3       s[3]!=t[3] j=next[3]=t[2]=a=t[3] 此时多余的比较,直接比较

nextval   -1-1-1-1 3                   s[4]与t[0] 对next数组进行修正nextval 
修正原则
t[j]=t[next[j]]  nextval[j]=next[j]
例如
                         j
          t=" a b c a b a a"
next        -1 0 0 0 1 2 1
nextval   -1 0 0-1 0 2 1

改进后的KMP算法如下:

/* KMP改进算法:利用nextval数组当 s= "a a a b a a a a b" t= "a a a a b" next -1 0 1 2 3 s[3]!=t[3] j=next[3]=t[2]=a=t[3] 此时多余的比较,直接比较s[4]与t[0] 对next数组进行修正nextval nextval -1-1-1-1 3 修正原则 t[j]=t[next[j]] nextval[j]=next[j] 例如 j t="a b c a b a a" next -1 0 0 0 1 2 1 nextval -1 0 0-1 0 2 1 */ void GetNextval(char* t, int nextval[]) { int k=-1; int i=0; int len = strlen(t); nextval[0] = -1; while(i=tlen) { return (i-tlen); } else { return (-1); } }

参考文献:

1、模式匹配的KMP算法详解  http://wenku.baidu.com/view/e91bed29647d27284b735194.html

2、《KMP 字符串模式匹配算法》教学课例  http://wenku.baidu.com/view/05460f35eefdc8d376ee3266.html

                                                                                          2010-10-10 20:36:47

你可能感兴趣的:(数据结构(C/C++))