算法【字符串匹配】| KMP算法详解

本文深入探讨了KMP算法,一种由James H. Morris、Donald Knuth和Vaughan Pratt提出的字符串搜索算法。KMP避免了重复字符的检查,通过next数组实现高效匹配。代码示例展示了如何获取next数组并进行字符串比较。
摘要由CSDN通过智能技术生成

一、简介

Knuth-Morris-Pratt字符串搜索算法(或KMP 算法)通过观察在发生不匹配时,单词本身包含足够的信息来搜索W主要“文本字符串”中出现的“单词”S来确定下
一个匹配的开始位置,从而绕过对先前匹配字符的重新检查。
该算法由James H. Morris构思,并由Donald Knuth “几周后”从自动机理论中独立发现。Morris 和Vaughan Pratt在 1970 年发表了技术报告。
三人也在 1977 年联合发表了该算法。独立地,1969 年,Matiyasevich [4] [5]发现了类似的算法,由二维图灵机编码,同时研究二进制字母表上的字符串
模式匹配识别问题。这是第一个用于字符串匹配的线性时间算法;
两个字符串匹配时,当两个字符相等则一起往后移动;
当出现不匹配时,就查找next数组,跳跃到最大前缀的位置继续匹配;
当跳跃的情况不满足子串匹配时,则主串的索引往后挪动;

二、图解

在这里插入图片描述
在这里插入图片描述

三、代码

#include <iostream>
#include <tuple>
#include <vector>
#include <string>
using namespace std;

string s1, s2;

/**
 * 获取next数组
 * */
vector<int> getNext(const string& s) {
    vector<int> vc;
    if(s.size() == 1) return vc;
    vc.resize(s.size());
    vc[0] = -1;
    vc[1] = 0;
    int i = 2;
    int cnt = 0;
    /* 生成数组 */
    while (i < s.size()) {
        if(s[i-1] == s[cnt]) vc[i++] = ++cnt;
        else if(cnt > 0) cnt = vc[cnt];
        else vc[i++] = 0;
    }
    return vc;
}

/** 字符串比较 */
int Kmp(const string& s, const string& subS) {
    if(s.empty() || subS.empty() || s.size() < subS.size()) return  -1;
    vector<int> str_next = getNext(subS);
    if (str_next.empty()) return -1;
    int i=0, j=0;

    while (i < s.size() && j < subS.size()) {
        if(s[i] == subS[j])  i++, j++;      // 当两个字符相等则往后移动
        else if(str_next[j] == -1)  i++;    // 当数组不能往前跳跃即没有相同前缀,则主串后移
        else j = str_next[j];               // 当没有匹配时,子串往前跳跃到相同前缀开始匹配
    }

    return j == subS.size() ? i - j : -1;
}

参考:
一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jxiepc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值