数据结构学习四(KMP算法实现)

8 篇文章 0 订阅
6 篇文章 0 订阅

算法思想描述:

KMP算法是通过分析模式串,预先计算每个位置发生不匹配的时候,可以省去重新匹配的的字符个数。整理出来发到一个next数组, 然后进行比较,这样可以避免字串的回溯,模式串中部分结果还可以复用,减少了循环次数,提高匹配效率。通俗的说就是KMP算法主要利用模式串某些字符与模式串开头位置的字符一样避免这些位置的重复比较的。例如 主串: abcabcabcabed , 模式串:abcabed。当比较到模式串'e'字符时不同的时候完全没有必要从模式串开始位置开始比较直接从模式串的'c'字符开始比较就可以了。并且主串也不用回溯了。

分析模式串过程,
    假设模式串当前位置与主串位置不同,如何利用模式串中当前位置之前与模式串开始出相同的字符。不用从开始相互比较。
    来一个例子:
    模式串p_s:abaabc  next[0-5] =0
    单前位置 next     复用字符数(j)    description
    0       next[0]=0  0        前面没有任何字符
    1       next[1]=0  0        当前字符前只有一个字符,无法服用的。
    2       next[2]=0  0        p_s[1]!=p_s[j]('a' != 'b',j = 0) ;
    3       next[3]=1  1        p_s[2]==p_s[j]('a' == 'a',j = 0);
    4       next[4]=1  1        p_s[3]!=p_s[j]('a' != 'b',j = 1);然后清空可复用字节数j=0,
                    但是不可一将next[4]直接赋值位0,虽然当前位置与之前位复用序
                    列比较已经无法在满足服用序列了。但其有可能满足一个新的所以
                    再次p_s[3]!=p_s[j]('a' != 'a',j = 0);
    5       next[5]=2  1        p_s[4]==p_s[j]('b' == 'b',j = 2);
        

代码如下:(本代码只经过本人的简单测试,可能存在问题。请相信自己的能力,敢于质疑。欢迎提供更好的、更快、更简洁的代码或者方法和指出错误。在ubuntu12.04使用gcc4.6.3版本编译,在vc中如出现错误,请谅解。)


void 
kmp_next(char p[], int next[], int pn)
{
	int i,j;
	
	next[1] =  0;
	next[0] = -1;

	i = -1; j = 0;
	while(j < pn){
		if(i == -1 || p[i] == p[j]) {i++,j++; next[j] = i;}
		else i = next[i];
	}




}

int
kmp(char s[], char p[], int sn, int pn)
{
	int next[MAX];
	int j =0, i = 0;

	if(sn > MAX) {

		printf("s is to long\n");
		return 0;
	}

	if(pn > sn) {
		return -1;
	}
	kmp_next(p, next, pn);
	while(i < sn) {
		if(j == -1 || s[i] == p[j]) {i++, j++; if(j>=pn) return i -pn;}
		else j = next[j];
	}

	return -1;
}


int 
main(int argc, char *argv[])
{
	char s[]="abababcabcabacababd";
	char p[MAX] = "bcc";
	int index, i;
	int next[MAX];
	
	while( scanf("%s", p) && strcmp(p, "#") != 0) {
	
		index = kmp(s, p, strlen(s), strlen(p));
		printf("%s\n", s);
		i = 0;
		while(i>=0 && i++ < index) printf(" ");
		printf("%s   |", p);
		printf("%d\n", index);
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值