c++ 实现KMP算法

使用C++实现KMP算法

KMP算法,全称为Knuth-Morris-Pratt算法,是一种快速匹配字符串的算法,常用于查找一个字符串在另一个字符串中的出现位置。本文将详细讲解如何使用C++实现KMP算法。

KMP算法的思路

KMP算法的核心思想是在匹配字符串时,尽可能减少比较的次数,从而提高匹配效率。具体来说,KMP算法利用匹配字符串中前缀和后缀的相似性,在匹配时通过一个模式串的“状态机”指引从而大幅减少比较的次数。

下面是KMP算法的主要流程:

  1. 初始化,设置两个指针i,j指向模式串p的第一个字符;
  2. 从左向右依次比较主串s中的每个字符和p中的对应字符;
  3. 当模式串p中第j个字符与主串s中的第i个字符相等时,则i,j同时后移;
  4. 当模式串p中第j个字符与主串s中的第i个字符不相等时,需要根据p中已匹配部分的“前缀”和“后缀”来决定下一步匹配的位置,具体而言:①当j==0时,i向右移动一位;②当j!=0时,j跳到p的前j-1个字符组成的子串中最长的“前缀”和“后缀”相等的位置的下一个位置,即j=next[j-1];
  5. 当模式串p中所有字符均已匹配,则匹配成功,返回i-p的长度,即主串中匹配到的开始位置;
  6. 当主串s中所有字符均已匹配完还没有匹配成功,则匹配失败,返回-1。

其中,next数组是KMP算法的关键。next数组记录的是针对每个字符,其之前的字符中最大前后缀匹配长度的值,它决定了在匹配过程中,模式串p中已匹配部分所形成的“状态机”从哪个位置开始继续匹配。next数组可通过类似动态规划的方式进行预处理。

C++实现

在C++中实现KMP算法,我们需要定义一个函数KMP(const char s, const char p),其中s是主串,p是模式串。KMP函数返回的是模式串在主串中匹配到的开始位置。下面是完整代码:

#include <iostream>
#include <cstring>

using namespace std;

void getNext(const char* p, int* next) {
    int i = 0;
    next[0] = 0;
    for (int j = 1; j < strlen(p); j++) { // 遍历模式串p
        while (i > 0 && p[i] != p[j]) {
            i = next[i - 1];
        }
        if (p[i] == p[j]) {
            i++;
        }
        next[j] = i;
    }
}

int KMP(const char* s, const char* p) {
    int i = 0, j = 0;
    int next[strlen(p)];
    getNext(p, next);
    while (i < strlen(s) && j < strlen(p)) {
        if (j == 0 || s[i] == p[j]) {
            i++;
            j++;
        }
        else {
            j = next[j - 1];
        }
    }
    if (j == strlen(p)) {
        return i - j;
    }
    else {
        return -1;
    }
}

int main() {
    const char* s = "ABCABE";
    const char* p = "ABE";
    int pos = KMP(s, p);
    if (pos != -1) {
        cout << "在主串中匹配到模式串的位置为:" << pos << endl;
    }
    else {
        cout << "匹配失败!" << endl;
    }
    return 0;
}

上面代码中的getNext函数用于预处理next数组,KMP函数用于匹配字符串,其实现方式即上文所述的KMP算法流程。

下面是两个实例说明,其中s是主串,p是模式串,pos表示p在s中的开始匹配位置:

  • s = "ABCABE", p = "ABE" => pos = 3
  • s = "AABAAAB", p = "AAA" => pos = 2

总结

本文详细讲解了如何使用C++实现KMP算法。在KMP算法的实现过程中,需要定义KMP函数和getNext函数,需要注意每个函数的作用和实现细节。在实际使用KMP算法时,我们只需要调用KMP函数即可。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++ 实现KMP算法 - Python技术站

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

相关文章

  • 谈谈Spring AOP中@Aspect的高级用法示例

    下面是关于“谈谈Spring AOP中@Aspect的高级用法示例”的完整攻略: 1. 了解@Aspect的作用 在Spring AOP中,@Aspect是一个非常重要的注解,用于定义切面。通过切面,我们可以在不改变原来业务逻辑的基础上,实现对我们所感兴趣的部分进行增强或修改,从而达到一些特定的目的。 2. @Pointcut注解的使用 @Pointcut是…

    C 2023年5月23日
    00
  • 网络工程师面试时喜欢问的问题与参考答案集锦

    网络工程师面试时,通常会涉及到网络基础知识、网络安全、网络管理和运维等方面的问题。以下是一些常见的问题及参考答案,供面试准备时参考。 一、网络基础知识 1. OSI七层模型和TCP/IP四层模型是什么? 答:OSI七层模型和TCP/IP四层模型都是计算机网络的层次模型。OSI七层模型包括:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。TCP/I…

    C 2023年5月22日
    00
  • C语言算法练习之抓交通肇事犯

    C语言算法练习之抓交通肇事犯 项目简介 抓交通肇事犯是一道经典的C语言算法练习题目。题目描述如下:一辆满载着5个人的车辆在道路上行驶,当它撞上一个人之后停下来了,由于事故发生时视线不好,司机不知道是哪个乘客撞上了行人,警察到达现场后询问了所有乘客,他们的回答如下: A说:“是B撞的人。” B说:“是C撞的人。” C说:“是D撞的人。” D说:“是C撞的人。”…

    C 2023年5月23日
    00
  • C语言 解压华为固件的实例代码

    下面我将详细讲解“C语言 解压华为固件的实例代码”的完整攻略。 1. 前置要求 在开始之前,我们需要先安装好以下工具: make gcc git wget 使用如下命令安装: sudo apt-get update sudo apt-get install -y make gcc git wget 2. 获取华为固件压缩包 首先,我们需要从华为的官方网站上获…

    C 2023年5月24日
    00
  • C语言有哪些特点?

    C语言是一种高级编程语言,具有以下特点: 1. 语言简洁、紧凑 相对于其他编程语言,C语言的核心语法非常简单且紧凑,没有过多的冗余语法,使得程序员可以快速地入手。同时,C语言提供了相对较少的预定义函数(如printf, scanf等),大部分函数都需要自己定义,这也有利于程序员更深入地理解计算机程序的本质。 例如,以下是C语言的“Hello World”程序…

    C 2023年4月27日
    00
  • VScode配置C语言环境完整版(亲测可用)

    以下是“VScode配置C语言环境完整版(亲测可用)”的完整攻略: 步骤一:安装MinGW编译器 访问MinGW官网(https://sourceforge.net/projects/mingw-w64/),下载适合自己操作系统版本的MinGW编译器安装程序,并进行安装。 打开安装目录下的bin文件夹,并将其中的mingw32-make.exe、gcc.ex…

    C 2023年5月23日
    00
  • 用C语言实现简单扫雷游戏

    使用C语言实现简单扫雷游戏需要以下步骤: 1. 设计游戏界面和游戏规则 游戏界面通常包括地图,雷数和计时器等元素。根据游戏规则,地图应该是一个矩形,且长宽可以自定义,地图中会布置一些地雷。游戏目标是找出所有不是地雷的方块,并标记地雷方块的位置。 2. 初始化地图和地雷分布 定义地图大小和雷数,并用二维数组来表示地图,将地图中所有元素赋为‘0’或’ ‘,表示未…

    C 2023年5月23日
    00
  • c++ vector模拟实现代码

    vector 模拟实现 —— 基本思路 Vector 是一个可以动态扩容的顺序容器,其内部使用数组存储数据。当 Vector 容量不足时,会自动扩容。通过复制当前容量大小的内存空间并将原元素复制到新的内存空间中来实现。 具体实现的过程可分为以下几个步骤: 定义容器的基本特性,包括存储元素的数组地址,当前元素数量,当前容量大小。 容器的初始化。初始化时分配一块…

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