【数据结构学习笔记】KMP算法的C语言实现

在了解KMP算法之前,我想想说说朴素算法
从主串的第pos个字符起和模式串的第一个字符进行比较
相等,就继续比较后面的
不相等,就从主串的下一个字符起重新和模式串的第一个字符尝试匹配
以此类推一直到匹配成功
朴素算法,易于理解和实现,但是效率很低,主串中的指针i有回溯
在最坏情况下,就是每一趟都是模式串的最后一个字符处出现失配的状态,一共的比较次数是m*(n-m+1),一半情况下n>>m所以时间复杂度O(m*n)

例如:主串000000000000000000000000000000000000000001
模式串00001
用朴素算法就不方便了

然后KMP算法就闪亮登场了
它对朴素算法进行的改进其实就是,主串的指针i不再回溯。而是利用已经得到的部分,将模式串尽可能向右滑动尽可能远的距离,再继续比较
滑动的距离是最大相同真前缀和真后缀的长度

为了知道失配时候,将从哪一个位置开始再次匹配,需要定义一共和模式串一样长的next【】数组

#include<stdio.h>
#include<malloc.h> 
#include <stdlib.h>
#include<string.h>

#define ok 1
#define error 0 
#define maxlen 40
int next[maxlen],nextval[maxlen];
int StrAssign(char s[],char c[])//创建一个字符串 
{
	int a;
	s;
	a=strlen(c);
	if(a>maxlen)
		return error;
	else
		s[0]=a;
		strcpy(&*(s+1),c);
		return ok;
}

int printstr(char s[])//输出一个字符串 
{
	int a;
	a=strlen(s);
	for(int i=1;i<=a;i++)
	{
		printf("%c",s[i]);
	}
	printf("\n\n");
}

int index_KMP(char s[],char t[],int pos) 
{
	int i=pos,j=1;
	while(i<=s[0]&&j<=t[0])
	{
		if(j==0||s[i]==t[j]){i++;j++;}
		else j=next[j];
	}
	if(j>t[0]) return i-t[0];
	else return 0;
 } 
int index_next(char s[])//求next函数 
{
	int i=1,j=0;
	next[1]=0;
	while(i<s[0])
	{
		if(j==0||s[i]==s[j]){++i;++j;next[i]=j;}
		else j=next[j];
	}
	printf("next 函数的值是");
	for(int i=1;i<strlen(s);i++)
	printf("%d",next[i]);
	printf("\n\n");
}
int index_nextval(char s[])//求nextval函数 (KMP的改进算法)
{
		int i=1,j=0;
	nextval[1]=0;
	while(i<s[0])
	{
		if(j==0||s[i]==s[j]){++i;++j;next[i]=j;
		if(s[i]!=s[j]) nextval[i]=j;
		else nextval[i]=nextval[j];}
		else j=nextval[j];
	}
	printf("nextval 函数的值是");
	for(int i=1;i<strlen(s);i++)
	printf("%d",nextval[i]);
	printf("\n\n");
}

int main()
{
	char ss1[40],ss2[40];
	char s1[40],s2[40];
	gets(s1);
	gets(s2);
	StrAssign(ss1,s1);//"abbaabbbaabbbb"
	StrAssign(ss2,s2);//"aabbbaabb"
	printf("主串为:");
	printstr(ss1);
	printf("模式串为:");
	printstr(ss2);
	index_next(ss2);
	index_nextval(ss2);
	int result;
	result=index_KMP(ss1,ss2,1);
	if(result) printf("在主串第%d处匹配成功\n",result);
	else printf("匹配失败\n");
 } 

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值