C语言kmp算法简单示例和实现原理探究

C语言KMP算法简单示例和实现原理探究

概述

KMP算法是一种字符串匹配算法,它能在O(n+m)的时间复杂度内匹配文本串和模式串。与简单的暴力匹配算法相比,它的时间复杂度更低。

实现原理

暴力匹配算法

在了解KMP算法之前,我们先来看一下暴力匹配算法,这是最简单的字符串匹配算法。

暴力匹配算法的实现原理是:假设文本串为T,模式串为P,从T的第一个字符开始,依次比较T和P的每个字符,如果相同,则接着比较下一个字符,如果不同,则从下一个字符重新开始匹配,直到将整个模式串匹配完为止。

KMP算法

KMP算法是一种比暴力匹配算法更高效的字符串匹配算法。它的核心思想是:当出现不匹配时,尽可能地利用已经匹配过的部分,减少模式串和文本串比较的次数。

计算最长公共前缀和最长公共后缀

KMP算法的第一步是计算出模式串的“最长公共前缀”和“最长公共后缀”。

最长公共前缀指的是,以模式串开头的那部分子串中,既是前缀又是后缀的最长子串。例如,模式串“abab”的最长公共前缀是“ab”。

最长公共后缀指的是,以模式串结尾的那部分子串中,既是前缀又是后缀的最长子串。例如,模式串“abab”的最长公共后缀是“ab”。

计算最长公共前缀和最长公共后缀的方法是,以模式串中每个字符为结尾,找到它前面的子串中既是前缀又是后缀的最大长度。此处使用一个next数组来存储最长公共前缀和最长公共后缀的值。

KMP算法实现流程

有了最长公共前缀和最长公共后缀的值之后,就可以开始实现KMP算法了。KMP算法的实现流程如下:

  • 从文本串T的第一个字符开始匹配模式串P的第一个字符。
  • 如果两个字符相等,则继续比较下一个字符。
  • 如果两个字符不相等,则根据next数组移动模式串。
  • 重复步骤2和步骤3,直到找到匹配或者文本串匹配完为止。

KMP算法的关键在于如何根据next数组移动模式串。

假设文本串T的当前位置是i,模式串P的当前位置是j,出现不匹配时,模式串需要移动的距离是k = j - next[j]。移动模式串的时候,需要将模式串的前k个字符跳过,从第k+1个字符开始继续比较。

关于next数组的计算

next数组的第一个元素next[0]必须是-1,表示移动模式串到第一个字符之前。next数组的其他元素计算方法如下:

  • next[0] = -1
  • 如果模式串的前j个字符(不包括第j个字符)与模式串的前k个字符(不包括第k个字符)匹配,则next[j] = k。
  • 如果模式串的前j个字符(不包括第j个字符)与模式串前缀的一个子串匹配,则递归地寻找匹配的最大长度,即next[k]。

示例

示例1

有一个文本串T:“ABCDABD”,和一个模式串P:“ABD”。

模式串P和文本串T的匹配过程如下:

  1. T[1]和P[1]相等,继续比较下一个字符;
  2. T[2]和P[2]相等,继续比较下一个字符;
  3. T[3]和P[3]不相等,根据next数组将P向右移动2个字符(即跳过AB),改成在T[3]和P[1]比较。
  4. T[3]和P[1]不相等,继续向右移动模式串,变成在T[3]和P[0]比较(即P前面加一个未匹配的字符)。
  5. T[3]和P[0]不相等,因为next[0]=-1,所以将模式串P向右移动1个字符;
  6. 继续比较T[3]和P[1],相等,继续比较下一个字符;
  7. T[4]和P[2]相等,继续比较下一个字符;
  8. T[5]和P[3]相等,完成匹配。

示例2

有一个文本串T:“ACABAABAACACAADABAA”,和一个模式串P:“AABAAC”。

模式串P和文本串T的匹配过程如下:

  1. T[1]和P[1]相等,继续比较下一个字符;
  2. T[2]和P[2]相等,继续比较下一个字符;
  3. T[3]和P[3]不相等,根据next数组将P向右移动3个字符(即跳过AAB),改成在T[3]和P[1]比较。
  4. T[3]和P[1]不相等,继续向右移动模式串,变成在T[3]和P[0]比较(即P前面加一个未匹配的字符)。
  5. T[3]和P[0]不相等,因为next[0]=-1,所以将模式串P向右移动1个字符;
  6. 继续比较T[3]和P[1],相等,继续比较下一个字符;
  7. T[4]和P[2]相等,继续比较下一个字符;
  8. T[5]和P[3]相等,继续比较下一个字符;
  9. T[6]和P[4]相等,继续比较下一个字符;
  10. T[7]和P[5]相等,完成匹配。

总结

KMP算法是一种高效的字符串匹配算法。通过计算模式串的最长公共前缀和最长公共后缀,可以减少模式串和文本串比较的次数,提高匹配效率。在实际开发中,可以使用KMP算法来实现字符串匹配功能,例如搜索引擎中的关键字查询等。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言kmp算法简单示例和实现原理探究 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C语言实现密码程序

    实现密码程序可以采用C语言编程,下面是实现密码程序的详细攻略: 步骤一:设计密码 首先需要确定你想要设计的密码类型和密码长度。一般来说,密码类型有数字、字母和符号,长度越长越安全。在编写程序之前,你需要确定一个密码并将其记录下来。 步骤二:编写代码 引入头文件和变量设置 首先引入stdio.h头文件,定义变量password、user_password和co…

    C 2023年5月23日
    00
  • ShareSDK造成App崩溃的一个BUG原因分析以及Fix方法

    让我们一步步讲解“ShareSDK造成App崩溃的一个BUG原因分析以及Fix方法”的完整攻略。 问题背景 在使用ShareSDK进行第三方分享的时候,存在一个BUG:在Android 9.0以上的设备上,使用ShareSDK的QQ和微信分享功能会造成App崩溃。 原因分析 经过分析,导致这个BUG的原因是因为ShareSDK中使用了一个过时的API导致的。…

    C 2023年5月23日
    00
  • C++实现高校人员信息管理系统

    C++ 实现高校人员信息管理系统 高校人员信息管理系统是一款常用的管理软件,它可以帮助高校管理人员和教师更加方便和快捷地管理学生和教职工的基本信息。本攻略将对该系统的实现进行详细讲解。 1.需求分析 首先,我们需要明确系统需要管理的基本信息,包括学生、教师和职工的姓名、性别、出生日期、学号(教职工号)、家庭住址等信息。 其次,系统需要支持添加、删除、修改学生…

    C 2023年5月23日
    00
  • 一篇文章弄懂C++左值引用和右值引用

    一篇文章弄懂C++左值引用和右值引用 在C++中,左值和右值是很重要的概念。我们可以使用左值引用和右值引用来访问不同类型的值。本文将详细讲解左值引用和右值引用的概念及其用法。 左值和右值 在C++中,每个表达式都具有左值或右值属性。左值是具有标识符的表达式,这些标识符可以作为左值出现在表达式中,例如变量、数组元素等等。右值是不能被放在赋值符号左边的表达式。 …

    C 2023年5月23日
    00
  • OPPO R1C怎么样?OPPO R1C发布时间及配置介绍

    OPPO R1C怎么样? 发布时间 OPPO R1C是2015年1月发布的,当时它的外观设计和拍照功能引起了很多人的关注。 配置介绍 外观设计 OPPO R1C采用了2.5D玻璃面板和金属边框的设计,具有非常优秀的手感和外观表现。另外,R1C还采用了悬浮玻璃后盖设计,整体视觉效果非常出色。 基本配置 OPPO R1C搭载了高通骁龙615的芯片,采用超大1/3…

    C 2023年5月23日
    00
  • 谈谈RxJava2中的异常及处理方法

    针对“谈谈RxJava2中的异常及处理方法”的问题,我可以提供以下完整攻略。 异常类型 在RxJava2中,一般有以下三种异常类型: Checked异常:如 IOException,必须使用 try/catch 块进行处理。 RuntimeException:如 NullPointerException,需要程序员的代码改进避免出现此类异常。此类异常也可以被…

    C 2023年5月23日
    00
  • C程序 打印180度旋转的简单左半边金字塔

    下面是关于“C程序 打印180度旋转的简单左半边金字塔”的完整使用攻略。 题目描述 要求编写一个C程序,能够打印一个180度旋转的简单左半边金字塔,并且能够输入金字塔的高度。 解决方案 首先,我们需要知道如何打印一个简单左半边金字塔。下面是一个简单的实现方法: #include <stdio.h> int main() { int height;…

    C 2023年5月9日
    00
  • mybatis plus常用注解的具体使用

    下面是关于MyBatis Plus常用注解的具体使用攻略。 简介 MyBatis Plus是一个开源的基于MyBatis的ORM框架,可以用于快速的进行Java Web应用的开发。MyBatis Plus提供了很多方便的注解,用于简化SQL语句编写和提高开发效率。 常用注解 @TableName @TableName 注解用于标识当前实体对应的表名。如果实体…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部