模式匹配:暴力匹配(BF),快速匹配(KMP)

模式匹配:

1.暴力匹配(BF):模式串和主串,从头开始匹配,如果遇到不匹配,则从头开始重新匹配,主串返回到原来起始位置向后移动一位。
在这里插入图片描述
然后一直查找直到最后找到
在这里插入图片描述最后匹配成功,将匹配成功后的剩余主串返回,并且输出。其匹配成功的下标应该为i-j ;
其适用范围为模式串中的重复字符较少的情况,时间复杂度较高,为O(m*n),m为字串长度,n为主串长度,空间复杂度较低为O(1)。

//暴力匹配 ,时间复杂度O(m*n)m为子串长度,n为主串长度 BF
char *my_strstr1(char *string, const char *strCharSet)
{
	assert(string != NULL && strCharSet != NULL);
	char *pdest = string;
	const char *psrc = strCharSet;
	int i, j;
	i = j = 0;
	while (pdest[i] != '\0'&& psrc[j] != '\0')
	{
		if (pdest[i]==psrc[j])
		{
			i++;
			j++;
		}
		else{
			i = i - j + 1;
			j = 0;
		}
	}
	if (psrc[j] == '\0')
		return string + i - j; 
	else
		return NULL;
}
int main()
{
	char s[] = "abababababaaaabababc";
	char t[] = "abababc";
	char *ar=my_strstr(s, t);
	printf(" s = %s\n", ar);
	system("pause");
	return 0;
}
2.快速匹配(KMP):
 对于暴力算法,如果出现不匹配字符,同时回退 主串和模式串的指针,嵌套 循环,时间复杂度 O(MN),空间复杂度 O(1)。
 KMP相对于暴力匹配来说时间复杂度大大降低,只需要O(m+n),
 对于KMP算法来说最主要的还是next 数组的实现。
 不说了,老表上图。

在这里插入图片描述

在这里插入图片描述下面的规律根据上面前后缀的最长相等长度很容易得到
在这里插入图片描述
写出next数组代码为:

void Next(char *pdest, int *next)
{
	int len = strlen(pdest);
	next[0] = 0;
	int j = 0;
	for (int i = 1; i < len; ++i)
	{                                                  
		while (j>0 && pdest[j] != pdest[i])
			j = next[j - 1];
		if (pdest[j] == pdest[i])
			j++;
		next[i] = j;
	}
}

得到了next 数组,老表们就可以根据next数组来进行匹配了,咱们接着上图,
在这里插入图片描述主串与模式串进行匹配,主要不同于BF的方面为,主串指针不回说,当匹配不当时,只移动模式串指针。
在这里插入图片描述当模式串与主串不匹配时,模式串指针根据next数组,进行回溯,
其指针回溯到其前一个next数组的值, 再此进行匹配,直到循环结束,

在这里插入代码片	while (pdest[i] != '\0' && psrc[j] != '\0')
	{
		if (pdest[i] == psrc[j])
		{
			i++;
			j++;
		}
		else{
			j = next[j-1];
		}
	}

循环有两个出口,判断其出口到底是匹配成功还是失败,成功就将后面的字符串返回,失败则返回-1.
最后,给大家附上KMP总代码

#include<stdio.h>
#include<windows.h>
#include<assert.h>
#include<string.h>
#include<stdbool.h>
#pragma warning(disable:4996)
void Next(char *pdest, int *next)
{
	int len = strlen(pdest);
	next[0] = 0;
	int j = 0;
	for (int i = 1; i < len; ++i)
	{                                                  
		while (j>0 && pdest[j] != pdest[i])
			j = next[j - 1];
		if (pdest[j] == pdest[i])
			j++;
		next[i] = j;
	}
}
char *my_strstr2(char *string, char *strCharstring)
{
	assert(string != NULL && strCharstring != NULL);
	char *pdest = string;
	char *psrc = strCharstring;
	int next[7];
	Next(psrc, next);
	int i, j;
	i = j = 0;
	while (pdest[i] != '\0' && psrc[j] != '\0')
	{
		if (pdest[i] == psrc[j])
		{
			i++;
			j++;
		}
		else{
			j = next[j-1];
		}
	}
	if (psrc[j] == '\0')
		return string + i - j;
	else
		return NULL;
}
int main()
{
	char s[] = "abababababaaaabababcccccc";
	char t[] = "abababc";
	char *ar = my_strstr2(s, t);
	printf(" s = %s\n", ar);
	system("pause");
	return 0;
}

欢迎大家指点。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值