KMP、BM、Sunday、Horspool、strstr字符串匹配算法的性能比较

KMP、BM、Sunday、Horspool、strstr字符串匹配算法的性能比较

一、简介

简介:字符串匹配算法,顾名思义,在一个给定的字符文本内搜寻出自己想要找的一个字符串,平常所用的各种文本编辑器里的ctrl+F大多就是使用的这些字符匹配算法。本文通过用c语言实现4种比较受欢迎的字符匹配算法,在同一文本下搜寻同一关键字符串,用来和c库函数strstr作时间上的性能比较,同时也对实现的4种算法做对应比较。各个算法名称如下:(对各个算法详细原理感兴趣的伙伴自行去查询,下面只做简要介绍,文中的T都代表文本串,即要搜索的范围,P代表要搜索的目标串,红色代表失配,黄色代表一些P串和T串中相同的字符)

1、strstr():c语言的库函数

函数原型:char* strstr(char* str1,char* str2);//包含在<string.h>中

原理简述:暴力匹配,从左到右依次匹配。

文本串T

A

B

C

F

D

L

K

             

模式串P

K

L

F

C

F

                 

第一次移动

K

L

F

C

F

               

第二次移动

K

L

F

C

F

             

2、KMP(Knuth-Morris-Pratt)算法:

原理简述:KMP相对strstr做了一些改进,它和strstr一样,都是从左到右依次匹配,当出现失配时,比如,文本串T是“ABCGHABDHKLOEM,”,模式串P是“ABCGHABCF”,当匹配到第八个字符“C”时失配,因为第一、二字符是“AB”,与当前失配字符“C”(第八个)的前两个字符刚好是一样的,于是将整个P串向右移动5个位置,使得第一、二个字符“AB”与文本串T中的"AB"相对,然后继续从P串的第三个字符“C”往后匹配(注意,与当前失配字符的前1个以上字符相等的字符必须是从P串第一个字符开始的,否则不算是满足规则,当不存在时,与strstr一样,只往前移动一个位置)。

文本串T

A

B

C

G

H

A

B

D

H

K

L

O

E

M

 

模式串P

A

B

C

G

H

A

B

C

F

           

第一次移动

开头有相同前缀,

A

B

C

G

H

A

B

C

F

 

第二次移动

开头无相同前缀

A

B

C

G

H

A

B

C

F

实现代码如下:

/*
function:KMP的next数组求解(预处理)
Param:
@p 需要匹配的字符串
@next 需要匹配的字符串对应的next数组
*/
void KMPPre(char* p, int KMP_next[])
{
    int pLen=strlen(p);
    KMP_next[0]=-1;
    int k=-1;
    int j=0;
    while(j<pLen-1){
        //p[k]表示前缀,p[j]表示后缀  
        if(k==-1||p[j]==p[k]){
            ++j;
            ++k;
            if(p[j]!=p[k])
                KMP_next[j]=k;
            else if(KMP_next[k]!=-1)//若是k是0的话,它的next[0]是-1,
                KMP_next[j]=KMP_next[k];
            else
                KMP_next[j]=0;
        }
        else{
            k=KMP_next[k];
        }
    }
}
/*
function:
		KMP字符匹配算法
Param:
@s 文本内容
@sLen 文本内容长度
@p 需要匹配的字符串
@pLen 需要匹配的字符串长度
@next[] 辅助数组
*/
char* KmpSearch(char* s,int sLen,char* p,int pLen,int next[])
{
	int i=0;
	int j=0;
	while(i<sLen&&j<pLen){
		//①如果j=-1(代表又回到了P串的开头第一个字符,因为next[0]=-1),或者当前字符匹配成功(即S[i]==P[j]),都令i++,j++    
		if(j==-1||s[i]==p[j]){
			i++;
			j++;
		}
		else{
			//②如果j!=-1,且当前字符匹配失败,则令i不变(当前s串失配的地方),j=next[j]    
			//next[j]即为j所对应的next值(其实就是和它含有相同前缀的地方,比如P为"AFHKAFOIU",则next[6]=2,即第7个字符“O”的前两个字符"AF"(第五、六个字符)有相同前缀"AF"(第一、二个字符))
			j=next[j];
		}
	}
	if(j==pLen){
		return &s[i-j];
	}
	else{
		return NULL;
	}
}

总结:原理不难理解,但是我们也发现了,KMP的匹配规则是和模式串P的内容有关系的,特别是对那种有大量重复字符的字符串有很大帮助,基于这个匹配规则,每次匹配一个模式串P时,都要相应生成一个辅助数组(人们都习惯成为next数组),这个数组记录着与模式串P中每个字符失配时需要移动的位置数有关的值。具体计算在此不做详细介绍,需要了解的伙伴自行查询。所有的实现代码在上面已给出。

3、BM(Boyer-Moore)算法:

原理简述:BM算法有两个匹配规则,一个是坏字符规则,另一个是好后缀规则。匹配顺序是从右向左(即从模式串p的最后一个字符开始匹配&#

  • 21
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值