看数据结构写代码(18) KMP算法

本文探讨了模式匹配算法,重点介绍了KMP算法,对比了它与暴力匹配算法的时间复杂度,并提供了KMP算法的代码实现。通过学习,读者可以理解KMP算法如何有效地查找子串在主串中的位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

字符串 求 子串 位置 的 算法 叫做 模式匹配算法。

模式匹配 算法 有 好多种,比较 常见的 有 暴力 匹配算法 和 KMP 算法。暴力匹配算法 时间 复杂度为O(M*N),KMP 时间复杂度为 O(M+N)。


下面给出两种算法的代码

欢迎指出代码不足

// KMP.cpp : 定义控制台应用程序的入口点。
//求子串问题..


#include "stdafx.h"
#include <cstring>
#include <cstdlib>

//暴力匹配算法,时间复杂度 为 O(m*n)
//求在 母串 s 从 第 pos 个位置开始 子串 t的位置
static int runTimes = 0;//执行次数...
int normal(char * s,char * t,int pos){
	int sLen = strlen(s);//母串的位置
	int tLen = strlen(t);//子串的长度
	int i = pos-1,j = 0;//计算起始值
	int first = i;//匹配开始的位置
	runTimes = 0;
	while (i <sLen && j < tLen){
		runTimes++;
		if (s[i] == t[j]) {//相等
			i++,j++;
		}
		else{//不相等,i = 匹配开始的值+1, j = 0
			i = ++first;
			j = 0;
		}
	}
	if (j >= tLen){//匹配成功.
		return first+1;
	}
	else{//匹配不成功,返回 -1
		return -1;
	}
}
//普通 求 Next
void getNext1(char * t,int len,int * next){
	next[0] = -1;//初值..
	int i = 0,j = -1;
	while (i < len -1){
		if(j == -1 || t[i] == t[j]){
			i++,j++;
			next[i] = j;
		}
		else{
			j = next[j];
		}
	}
}
//求Next  改进
void getNext2(char * t,int len,int * next){
	next[0] = -1;//初值..
	int i = 0,j = -1;
	while (i < len -1){
		if(j == -1 || t[i] == t[j]){
			i++,j++;
			if (t[i] != t[j]){
				next[i] = j;
			}
			else{
				next[i] = next[j];
			}
		}
		else{
			j = next[j];
		}
	}
}

//kmp 模式匹配法.
int kmp(char * s,char * t,int pos,int fun){
	int sLen = strlen(s);
	int tLen = strlen(t);
	int i = pos - 1,j = 0;
	int * next = (int *) malloc(sizeof(int) * tLen);//next 数组
	if (fun == 1){
		getNext1(t,tLen,next);//计算next
	}
	else{
		getNext2(t,tLen,next);//计算next
	}
	runTimes = 0;
	while (i < sLen && j < tLen){
		runTimes ++;
		if (j == -1 || s[i] == t[j]){
			i++,j++;
		}
		else{//i值 不回溯,j = next[j]
			j = next[j];
		}
	}
	free(next);//释放空间..
	if (j >= tLen){
		return i - j + 1;
	}
	return -1;
}

//打印 信息 
//kind , 1: 暴力匹配 2:KMP 3.改进KMP
void printMsg(char * string,int index,int kind){  
	if (index != -1){
		char * point = string + index - 1;   
		char *s = NULL;
		if (kind == 1){
			s = "暴力匹配";
		}
		else if(kind == 2){
			s = "kmp匹配";
		}
		else{
			s = "改进kmp匹配";
		}
		printf("%s 求得字符串为:%s,\t执行次数%d\n",s,point,runTimes); 
	} 
} 

int _tmain(int argc, _TCHAR* argv[])
{
	char * string = "abcdefghijklmnsdfdsdfsfdsd";  
    char * sub = "sdfd";  
	int index = normal(string,sub,1);
	printMsg(string,index,1);
	index = kmp(string,sub,1,1);
	printMsg(string,index,2);
	index = kmp(string,sub,1,2);
	printMsg(string,index,3);
	string = "0000000001100000000011000000000111000000000001111aa";  
    sub = "000000000001111";    
	index = normal(string,sub,1);
	printMsg(string,index,1);
	index = kmp(string,sub,1,1);
	printMsg(string,index,2);
	index = kmp(string,sub,1,2);
	printMsg(string,index,3);
	return 0;
}



参考书籍:严蔚敏《数据结构。C语言版》


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值