【数据结构】串的模式匹配:简单的模式匹配算法,KMP算法

 欢~迎~光~临~^_^

目录

知识树

1、什么是串的模式匹配 

2、简单的模式匹配算法

3、KMP算法

3.1 算法原理

3.2 C语言实现KMP算法 

3.3 求next数组

3.4 KMP算法优化(对next数组的优化) 


知识树

 

1、什么是串的模式匹配 

        串的模式匹配是在一个字符串中查找另一个较小的字符串(称为模式)的过程。模式匹配的目的是在文本串中查找一个或多个匹配字符串。这种搜索可以使用各种算法进行,包括暴力算法,KMP算法和Boyer-Moore算法等。模式匹配广泛应用于文本编辑器、搜索引擎、计算机网络和计算机安全等领域。

2、简单的模式匹配算法

        这个算法的时间复杂度是O(mn),其中m是模式串的长度,n是文本串的长度。在最坏情况下,即文本串中的每个字符都匹配模式串中的每个字符,时间复杂度为O(m(n-m+1)),因此朴素模式匹配算法在处理大型文本串时可能会变得很慢。

#include <stdio.h>
#include <string.h>int naive_search(const char text[], const char pattern[]) {int text_len = strlen(text);int pattern_len = strlen(pattern);for (int i = 0; i <= text_len - pattern_len; i++) {int j;for (j = 0; j < pattern_len; j++) {if (text[i + j] != pattern[j])break;}if (j == pattern_len)return i;}return -1;
}int main() {char text[] = "ABABCABCABABABD";char pattern[] = "ABABD";int pos = naive_search(text, pattern);if (pos >= 0)printf("Pattern found at position %d in the text.", pos);elseprintf("Pattern not found in the text.");return 0;
}

3、KMP算法

3.1 算法原理

        KMP算法是一种字符串匹配算法,它的原理是利用已知的信息尽可能减少匹配次数。KMP算法的核心是一个跳转表格,也称为Next数组或失配函数。

        在匹配的过程中,当发现不匹配的情况时,KMP算法会利用跳转表格中已经计算好的信息,直接跳过部分不需要匹配的字符,从而减少匹配次数。具体来说,KMP算法会根据当前匹配的位置和已知的信息,计算出下一个字符需要匹配的位置,从而避免了不必要的匹配操作。

        KMP算法的时间复杂度为O(m+n),其中m和n分别为模式串和文本串的长度,求next数组时间复杂度O(m);模式匹配过程最坏时间复杂度O(n)。相比于朴素的字符串匹配算法,KMP算法在匹配效率和性能上有了很大的提高。

3.2 C语言实现KMP算法 

        下述代码中,next()函数用于计算模式串的next数组,kmp()函数用于在文本串中查找模式串。在main()函数中,首先输入文本串和模式串,然后调用next()函数生成模式串的next数组,最后调用kmp()函数在文本串中查找模式串。若模式串存在于文本串中,输出模式串在文本串中的位置,否则输出不存在的信息。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>void next(char *pattern, int *next_arr) {int i = 0, j = -1;next_arr[0] = -1;int len = strlen(pattern);while (i < len - 1) {if (j == -1 || pattern[i] == pattern[j]) {i++;j++;next_arr[i] = j;} else {j = next_arr[j];}}
}int kmp(char *text, char *pattern, int *next_arr) {int i = 0, j = 0;int text_len = strlen(text), pattern_len = strlen(pattern);while (i < text_len && j < pattern_len) {if (j == -1 || text[i] == pattern[j]) {i++;j++;} else {j = next_arr[j];}}if (j == pattern_len) {return i - j;} else {return -1;}
}int main() {char text[100], pattern[100];int next_arr[100];printf("请输入文本串:");gets(text);printf("请输入模式串:");gets(pattern);next(pattern, next_arr);int index = kmp(text, pattern, next_arr);if (index != -1) {printf("模式串在文本串中的位置是:%d\n", index);} else {printf("文本串中不存在模式串!\n");}return 0;
}

3.3 求next数组

        next(j)的含义是:在子串的第j个字符与主串发生失配时,则跳到子串的next(j)位置重新与主串当前位置进行比较。
        next(1)都无脑写0;next(2)都无脑写1;
        其他next:在不匹配的位置前,划一根分界线,模式串一步一步往后退,直到分界线之前“能对上”,或模式串完全跨过分界线为止,此时 j 指向哪,next数组值就是多少。

void next(char *pattern, int *next_arr) {int i = 0, j = -1;next_arr[0] = -1;int len = strlen(pattern);while (i < len - 1) {if (j == -1 || pattern[i] == pattern[j]) {i++;j++;next_arr[i] = j;} else {j = next_arr[j];}}
}

        在上述代码中,pattern表示模式串,next_arr表示next数组。首先将next_arr[0]置为-1,i表示当前已匹配的字符数,初始值为0,j表示当前已匹配的字符中,能和下一位字符匹配的最长前缀的末尾位置,初始值为-1。在循环中,若第i个字符能和第j+1个字符匹配,则更新next_arr[i+1]=j+1,否则将j更新为next_arr[j],重复此过程直到结束。

例1,若模式串为ABCDABD,则next数组为[-1, 0, 0, 0, 0, 1, 2, 0]

例2,下面是"ababaaababaa"模式串对应的next数组值:

- a b a b a a a b a b a a
- 0 0 1 2 3 4 5 2 3 4 5 6

因此,"ababaaababaa"模式串的next数组值为[0, 0, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6]。

next数组的生成过程是KMP算法的核心部分,它可以大大提高模式匹配的效率。

3.4 KMP算法优化(对next数组的优化) 

                KMP算法优化:可以采用KMP算法的优化手段,通过推导next[j]和nextval[next[j]]的关系,减少计算次数。

//核心代码
nextval[1]=0;  
for(int j = 2;j < pattern.length;j++)
{if(pattern[next[j]] == pattern[j])nextval[j] = nextval[next[j]];elsenextval[i] = nextval[j];
}

🤞❤️🤞❤️🤞❤️串的模式匹配的知识点总结就到这里啦,如果对博文还满意的话,劳烦各位看官动动“发财的小手”留下您对博文的赞和对博主的关注吧🤞❤️🤞❤️🤞❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/109870.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#,数值计算——Hashfn1的计算方法与源程序

1 文本格式 using System; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer { public class Hashfn1 { private Ranhash hasher { get; set; } new Ranhash(); private int n { get; set; } public Hash…

栈与队列经典题目——用队列实现栈

本篇文章讲解栈和队列这一部分知识点的经典题目&#xff1a;用栈实现队列、用队列实现栈。对应的题号分别为&#xff1a;Leetcode.225——用队列实现栈&#xff0c;。 在对两个题目进行解释之前&#xff0c;先回顾以下栈和队列的特点与不同&#xff1a; 栈是一种特殊的线性表…

怎么激活IDM

IDM是一个下载软件。 激活它需要用到git上面的一个项目&#xff0c;同时网络要能连到github GitHub - lstprjct/IDM-Activation-Script: IDM Activation & Trail Reset Script WINR 输入powershell 输入命令行 iex(irm is.gd/idm_reset) 或者 iwr -useb https://raw.…

Unity - Shader Compiled Log

文章目录 吐槽开启 Log Shader Compilation实践资源准备Build ABTesting ScriptShader Compiled Log Project 吐槽 先说一下&#xff0c;最近几天前&#xff0c;纷纷看到 unity install fee 的天才收费方案 真的忍不住吐槽&#xff0c;我只想说&#xff1a; “no zuo no die”…

easycms v5.5 分析 | Bugku S3 AWD排位赛

前言 这个awd打的悲&#xff0c;后台默认用户名密码为admin:admin&#xff0c;但是几乎所有人都改了 而且一进去看到这个cms就有点懵逼&#xff0c;都不知道这个cms是干嘛的&#xff08;没用过相似的cms&#xff09; 虽然网上找出了很多相关的漏洞&#xff0c;但是不知道为什…

山洪灾害预警方案(山洪预警解决方案的组成)

​ 随着气候变化的不断加剧&#xff0c;山洪灾害在许多地区成为了极具威胁性的自然灾害之一。为了帮助地方政府和居民更好地预防和应对山洪灾害&#xff0c;我们设计了一套基于星创易联的SR600工业路由器和DTU200的山洪灾害预警方案&#xff0c;并成功在某地区进行了部署。 案…

HTML显示中文空格字符,emsp;一个中文字符,ensp;半个中文字符

&emsp;一个中文字符 &ensp;半个中文字符 <ul><li class"li">姓&emsp;&emsp;名&#xff1a;<input type"text" /></li><li class"li">手&ensp;机&ensp;号&#xff1a;<input type"…

idea装载jerbel以及文件上传下载

一、JRebel 1.1 Jrebel介绍 JRebel是一个Java开发工具&#xff0c;它是一款用于实时代码重载的插件。它的主要功能是在不重新启动应用程序的情况下&#xff0c;将修改后的Java代码实时应用到正在运行的应用程序中&#xff0c;从而加快开发周期&#xff0c;提高开发效率。 实…

编程获取图像中的圆半径

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 即将推出EmguCV的教程&#xff0c;请大家还稍作等待。 之前网友咨询如何获得图像中圆形的半径&#xff0c;其中有两个十字作为标定…

Golang代码漏洞扫描工具介绍——govulncheck

Golang Golang作为一款近年来最火热的服务端语言之一&#xff0c;深受广大程序员的喜爱&#xff0c;笔者最近也在用&#xff0c;特别是高并发的场景下&#xff0c;golang易用性的优势十分明显&#xff0c;但笔者这次想要介绍的并不是golang本身&#xff0c;而且golang代码的漏洞…

stu01-IDEA怎么创建一个HTML项目

1.打开idea&#xff0c;依次点击file→new→project 2.点击Java&#xff0c;选择你的jdk&#xff0c;没有下载的点击“Download JDK”/已经下载有JDK但在这里没显示的→点击“Add JDK”&#xff0c;选择你安装的JDK的路径&#xff0c;然后next 3.next 4.起好名字&#xff0c;我…

【C++】类和对象(中下)

前言&#xff1a; 上一篇文章&#xff0c;我们了解了类的默认成员函数——构造函数、析构函数、拷贝构造函数&#xff0c;这篇我们让我们接着了解。 一、赋值运算符重载&#xff1a; 1.运算符重载&#xff1a; C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是…