模式匹配KMP

简介:

字符串朴素模式匹配算法的2种实现:

//1.朴素的模式匹配算法,用while实现

int StrStr_While(const char* pStr, const char* pSub, int* pos)
{
	int nRet = 0;
	int pStrLen = strlen(pStr);
	int pSubLen = strlen(pSub);
	int i = 0, j = 0;
	int nLen = pStrLen - pSubLen;

	if (pStr == NULL || pSub == NULL)
	{
		nRet = -1;
		printf("param input error!");
		return nRet;
	}

	while (i < pStrLen && j < pSubLen)
	{
		if (*(pStr + i) == *(pSub + j))
		{
			++i;
			++j;
		}
		else
		{
			i = i - j + 1;
			j = 0;
		}
	}

	if (j == pSubLen)
		*pos = i - j + 1;

	return nRet;
}


 

//2.朴素的模式匹配,用for循环实现

int StrStr_For(const char* pStr, const char* pSub, int* pos)
{
	int nRet = 0;
	int pStrLen = strlen(pStr);
	int pSubLen = strlen(pSub);
	int i = 0, j = 0;
	int nLen = pStrLen - pSubLen;

	if (pStr == NULL || pSub == NULL)
	{
		nRet = -1;
		printf("param input error!");
		return nRet;
	}

	for (i = 0; i <= nLen; ++i)
	{
		for (j = 0; j < pSubLen; ++j)
		{
			if (*(pStr + i + j) != *(pSub + j))
				break;
		}

		if (j == pSubLen)
		{
			*pos = i + 1;
			break;
		}
	}
	
	return nRet;
}


 

实现字符串的匹配有高效的算法。那就是KMP算法,实现例如以下:

//取得KMP算法须要用的的next数组

int GetNext(const char* pStr, int nNext[])
{
	int nRet = 0;
	if (pStr == NULL || nNext == NULL)
	{
		nRet = -1;
		printf("param input error!\n");
		return nRet;
	}

	int nLen = strlen(pStr);
	int i = 0, j = -1;
	nNext[i] = j;
	while (i < nLen - 1)
	{
		if (j == -1 || pStr[i] == pStr[j])
		{
			++i;
			++j;
			nNext[i] = j;
		}
		else
		{
			j = nNext[j];
		}
	}

	return nRet;
}



//取next数组的改进型算法!剔除多个反复字符的next数组值持续增长。

int GetNextVal(const char* pStr, int nNext[])

{

	int nRet = 0;

	if (pStr == NULL || nNext == NULL)

	{

		nRet = -1;

		printf("param input error!\n");

		return nRet;

	}



	int nLen = strlen(pStr);

	int i = 0, j = -1;

	nNext[i] = j;

	while (i < nLen - 1)

	{

		if (j == -1 || pStr[i] == pStr[j])

		{

			++i;

			++j;

			if (pStr[i] != pStr[j])

				nNext[i] = j;

			else

				nNext[i] = nNext[j];

		}

		else

		{

			j = nNext[j];

		}

	}



	return nRet;

}



 

这是针对类似aaaaaaab这种字符串使用上面两个函数取得的next数组值得比較。注意书上的都是字符串从数组的下标为1的位置開始存储的。我改进的算法是还是让字符串从数组下标为0的位置開始存储。

所以上面的next数组值都要相较与原来的值减1。

 

//调用上面的函数实现KMP高效字符串模式匹配算法!


int Index_KMP(const char* pStr, const char* pSub, int* nPos)
{
	int nRet = 0;
	if (pStr == NULL || pSub == NULL || nPos == NULL)
	{
		nRet = -1;
		printf("param input error!\n");
		return nRet;
	}

	int pStrlen = strlen(pStr);
	int pSublen = strlen(pSub);

	int nNext[255] = { 0 };
	//nRet = GetNext(pSub,nNext);
	nRet = GetNextVal(pSub, nNext);
	if (nRet != 0)
	{
		printf("call GetNext() func is error!\n");
		return nRet;
	}

	int i = 0, j = 0;
	while (i < pStrlen && j < pSublen)
	{
		if (j == -1 || *(pStr + i) == *(pSub + j))
		{
			++i;
			++j;
		}
		else
		{
			j = nNext[j];
		}
	}

	if (j == pSublen)
		*nPos = i - j + 1;

	return nRet;
}






本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5174879.html,如需转载请自行联系原作者

相关文章
|
编译器 C++
【C++】类和对象(中)之构造函数与析构函数
【C++】类和对象(中)之构造函数与析构函数
209 0
|
JavaScript 前端开发
js实现数据的双向绑定
js实现数据的双向绑定
224 59
|
数据库 开发者
|
弹性计算 容灾 对象存储
阿里云2核4G5M服务器一年和五年价格表_轻量和ECS租用费用
2023阿里云2核4G5M服务器一年和五年价格表_轻量和ECS租用费用
562 0
阿里云2核4G5M服务器一年和五年价格表_轻量和ECS租用费用
|
编译器 图形学 C语言
SSE2 指令集简介以及与SSE的差别
SSE2,Intel在2001年为Pentium 4引入的扩展,增强了SSE的功能,添加了对双精度浮点和64位整数运算的支持,新增144条指令,提升向量处理能力。SSE2的C代码示例展示了如何通过`_mm_add_ps`加速向量加法。启用SSE2编译器支持可优化处理图像、音频和视频等大量计算任务的性能。
|
弹性计算 Ubuntu 安全
阿里云服务器镜像选择全指南:不同类型的镜像区别及选择参考
阿里云服务器镜像,作为ECS实例的“装机盘”,不仅提供了操作系统,还包含了初始化应用数据和预装软件。选择合适的镜像对于云服务器的性能和稳定性至关重要。本文将详细解析阿里云服务器提供的多种镜像类型,包括公共镜像、自定义镜像、共享镜像、云市场镜像和社区镜像,以供参考和选择。
阿里云服务器镜像选择全指南:不同类型的镜像区别及选择参考
|
数据安全/隐私保护
ensp中基本acl 原理及配置命令(详解)
ensp中基本acl 原理及配置命令(详解)
927 1
|
网络协议 应用服务中间件 Linux
centos7下Nginx正向代理操作步骤
centos7下Nginx正向代理操作步骤
241 0
|
前端开发
CSS外边距重叠:原理、结果
CSS外边距重叠:原理、结果
|
Java
Java实现数组求和
Java实现数组求和
255 0