KMP算法(C语言实现)

这篇具有很好参考价值的文章主要介绍了KMP算法(C语言实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

博主的博客主页:CSND博客
Gitee主页:博主的Gitee
博主的稀土掘金:稀土掘金主页
博主的b站账号:程序员乐
公众号——《小白技术圈》,回复关键字:ml学习资料。1T学习资料免费分享给你。

KMP算法(C语言实现)


思路

在经典的字符串匹配中,如果字符匹配失败i会返回到开始匹配时的后一个字符。这样会导致效率的下降。在KMP算法中,即使匹配失败i也不会动,只会J进行移动。

KMP算法(C语言实现)

在匹配的过程中,字符相同时,就会进行下一对字符的匹配。当不相同时,如下面:

KMP算法(C语言实现)

匹配失败,此时j需要回退,要回退到哪里呢?回退到下标为2的地方处。
原因如下:
i前面的字符都是匹配成功的,j前面的字符也是匹配成功的。常规情况下j要从头开始进行匹配,如果发现j前面的子串存在两个相同的真子串时(以下标0开始,以下标j-1结束),那么j就退回到真子串长度的位置处。如下面:

KMP算法(C语言实现)

近一步解释,i前面的串和j前面的串相等,匹配时一定是从下标为0的位置匹配的,这也是找——以下标0开始,以下标j-1结束串——的原因,如果存在这两个串,则说明i前面一定存在以下标0开始,以下标j-1结束串的子串。这样J退回的时候就省去了从头开始进行匹配。

这个串每个字符都有可能进行回退。回退的位置用一个数组进行储存,就形成了next数组

next数组

KMP算法(C语言实现)
默认:0号位回退到-1处(在代码中处理,将不会造成数组越界问题)
1号位匹配失败退到0处。
现在主要的问题是如何实现next数组。

我们用K表示返回位置的下标,p是字符串,j表示下标。
假设next[j]=k成立(表达在j处匹配失败后返回到以k为下标处的位置)
那么p[0]····p[k-1]==p[x]····p[j-1]
(k处位置是从新匹配的地方,它前面的子串一定和j前面的子串相同)
从上面那个式子可以看出k-1-0=j-1-x即x=j-k;
式子就变成了p[0]····p[k-1]==p[j-k]····p[j-1] ——>next[j]=k成立的情况下
1️⃣当p[j]=p[k]
上面的式子可以变成p[0]····p[k-1] p[k]==p[j-k]····p[j-1] p[i]——>next[j+1]=k+1
2️⃣当p[j],p[k]不相等时,就会回退到k处,如果此时的k所对应k1,p[k1]=p[j]
那么next[j+1]=k1+1,否则继续回退,直到相等或者为-1处停止。
经过这样的过程,我们就得到了next数组

下面用图片给以进一步解释:下面的i是j,手残写错字母了。
KMP算法(C语言实现)

next数组优化——>nextval数组

KMP算法(C语言实现)

nextval数组的实现是根据next数组来实现的。
具体的求法:nextval数组的第一个元素为-1,第二个元素位0,以后j下标所对应的字符如果和以k对应的字符相等,那么nextval的元素nextval[k]中的元素。如果不相等,nextval的元素next里面的元素(即为k的值)文章来源地址https://www.toymoban.com/news/detail-421152.html

nextval数组

void my_nextval(int* nextval, char* p, int n)
{
	int k = -1, j = 0;
	nextval[0] = -1;
	while (j < n)
	{
		if (k == -1|| p[j] == p[k])
		{
			j++;
			k++;
			nextval[j] = k ;
			if (p[j] != p[k])
				nextval[j] = k;
			else
				nextval[j] = nextval[k];
		}
		else
		{
			k = nextval[k];
		}
	}
}

代码实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
void my_next(int* next,int n,const char* p)
{
	int j = 0,k=-1;
	next[0] = -1;
	while(j<n)
	{
		if (k == -1 || p[j] == p[k])
		{
			next[j + 1] = k + 1;
			j++;
			k++;
		}
		else
		{
			k = next[k];
		}
	}
}
int kmp(const char* str1, const char* str2)
{
	int i = 0, j = 0;
	int len = (int)strlen(str2);
	//next数组
	int* next = (int*)malloc(len * sizeof(int));
	assert(next);
	my_next(next,len-1,str2);
	while (str2[j])
	{
		if(j==-1||str1[i] == str2[j])
		//j为-1时该位置下的i不会匹配成功,进入下一次匹配
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];//j进行回退
		}
		if (str1[i] == '\0')
		{
			free(next);
			next = NULL;
			return -1;
		}
	}
	free(next);
	next = NULL;
	return i;
}
int main()
{
	char arr[] = "abaabcdabcab";
	char brr[] = "ef";
	printf("%d\n",kmp(arr, brr));
	return 0;
}

到了这里,关于KMP算法(C语言实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • KMP算法【C++实现】

    BF算法 字符串匹配,我们一般思路是被对比的串作为主串,对主串的的每一个字符串作为子串的开头,与要匹配的字符串进行匹配,匹配不成功则子串开头+1,要匹配的字符串回溯到1,进行匹配,直到匹配成功或者主串全部遍历完成,这就是BF算法。 分析时间复杂度,假设主

    2023年04月27日
    浏览(53)
  • KMP算法 Java实现

    Problem: 28. 找出字符串中第一个匹配项的下标 目录 解题方法 思路 构建next数组 回溯查找 复杂度 Code 构建next串 回溯查找next串,最后下标 通过最大前缀后缀能找到下一次未查找到后要回溯的位置 无论如何第一个数的下一次回溯位置肯定是0,因此 next[0]=0 这里的 j 表示前缀起始位

    2024年04月17日
    浏览(26)
  • KMP算法(多种实现方式)

    利用已经匹配的数据,去除无效的从头匹配 首先我们找到 i=9,j=9时不匹配,如果时暴力算法,此时i应重新来到i=2的位置,j返回j=1的位置,开始新一轮的匹配 这样暴力匹配,就白白浪费了已经匹配的串,那么问题来了,我们应该如何利用已经匹配的串呢?? 我们看着图片,假设i返回i=2,j返回

    2024年02月08日
    浏览(31)
  • 【工具使用】Gitee+PicGo实现图床 快速上传本地md文件至博客(非常稳定)

    为了可以非常方便的将本地写好的md笔记直接复制粘贴到博客中, 解决方案是:图片放到服务器上,md文件直接请求服务器上的图片 ,这样可以直接复制所有md内容至网上发布,而不需要再单独上传图片。 实现方案:图床 为了可以非常方便的将本地写好的md笔记直接复制粘贴

    2024年02月02日
    浏览(27)
  • 关于Gitee上传代码以后主页没有显示贡献度(没有显示小绿块)

    当我首次发现这个问题的时候,我毫无波澜的认为是Gitee出现了BUG。因为我的这些空白天数里都是有提交的,怎么会没有贡献呢?肯定只是没有显示而已。 可以看到,我这些天都是有贡献的,那为什么没有显示呢? 抱着科学又严谨的心态,我决定一探究竟。首先就在常用的网

    2024年02月07日
    浏览(31)
  • Web大学生网页作业成品:个人博客主页 (纯HTML+CSS代码)

    🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (1000套) 】 🧡 程序员有趣的告白方式:【💌HTML七夕情人节表白网页制作 (

    2024年02月03日
    浏览(39)
  • 优先看我的博客:工控机 Ubuntu系统 输入密码登录界面后界面模糊卡死,键盘鼠标失效(不同于其他博主的问题解决方案,优先看我的博客。)

            (不同于其他博主的问题解决方案,工控机Ubuntu的系统   优先看我的博客。) 系统版本: ubuntu18.04 主机: 工控机 应用场景: 电力系统巡检机器人,工控机外hdmi接显示器,外接鼠标键盘。 问题: 之前在自己公司测试工控机可正常工作,但是发往客户现场后出现问

    2024年01月17日
    浏览(40)
  • 【数据结构】模式匹配之KMP算法与Bug日志—C/C++实现

    ​ 🌈 个人主页: Sarapines Programmer 🔥  系列专栏: 《数据结构奇遇记》 🔖墨香寄清辞: 墨痕寄壮志,星辰梦未满。 通幽径心凝意,剑指苍穹势如山。 目录 🌞1. 模式匹配的基本概念 🌞2. 模式匹配的解决办法 🎈2.1 暴力匹配(BF)算法 🎈2.2 KMP算法 🤖2.3 BUG记录_KMP算法 1

    2024年02月04日
    浏览(41)
  • gitee搭建个人博客教程

    基础环境: gitee账号、git、node.js、npm、Typora(需要版本高一点) 个人博客 创建账号同名的仓库 获取账号名方式如下,去掉@号的部分。 创建一个和你gitee账号同名的仓库,这样就可以用https://账号名.gitee.io/来访问。 填写仓库名称即可,但建议勾选上设置模板----Readme文件。

    2024年02月09日
    浏览(36)
  • docsify & gitee 搭建个人博客

    npm是Node.js的包管理器,用于安装和管理JavaScript包。要安装npm,需要先安装Node.js。以下是在不同操作系统上安装npm的步骤: 1.1 在Windows上安装npm: 访问Node.js官方网站(https://nodejs.org)。 在下载页面上,选择适用于Windows的LTS版本(长期支持版本)的Node.js安装程序。 下载安装

    2024年02月12日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包