首页 > 编程语言 >【杂乱笔记】Kmp字符串匹配算法

【杂乱笔记】Kmp字符串匹配算法

时间:2024-08-19 15:51:48浏览次数:18  
标签:匹配 int pattern prefix len next 算法 杂乱 Kmp

KMP 算法逻辑

  1. 构建 next 数组
    • 初始化 next 数组,用于存储每个位置的最长相同前后缀长度。
    • 遍历模式字符串patt
      • 如果当前字符与前缀字符匹配,增加前缀长度,并更新 next 数组。
      • 如果不匹配,使用 next[prefix\_len - 1] 回退到上一个可能的前缀长度,继续比较。
  2. 字符串匹配
    • 初始化两个指针 ij,分别指向文本 text 和模式 pattern 的开头。
    • 遍历文本:
      • 如果 text[i]pattern[j] 匹配,移动 ij
      • 如果 j 达到模式长度,说明匹配成功,记录匹配起始位置。
      • 如果不匹配且 j > 0,使用 next[j - 1] 回退 j,继续比较。
      • 如果 j == 0,仅移动 i
  3. 返回结果
    • 如果找到匹配,返回起始索引。
    • 如果没有匹配,返回 -1。

Next数组计算中,如果遇到当前字符与前缀字符不匹配的情况,那么就需要重新在前面遍历的内容中寻找次长的最长相同前后缀(对应代码为prefix_len = next[prefix_len - 1];),之后再与当前字符进行匹配(下一次while循环中的 if (patt[i] == patt[prefix_len])),如果还是匹配不上,那么就再再去之前的最长相同前后缀再次比较。

eg:

某一patt如下:

PattABCABD
Next000120

在匹配D时,我们当前的最长前后缀为AB,这时候通过代码prefix_len = next[prefix_len - 1];,我们相当于是去第一个AB中重新匹配,结果发现还是不匹配并且Next数组对应为0,所以DNext就为0。

#include <iostream>
#include <vector>
#include <string>

using namespace std;

vector<int> buildNext(const string& patt) {
    int m = patt.size();
    vector<int> next(m, 0);
    int prefix_len = 0;
    int i = 1;

    while (i < m) {
        if (patt[i] == patt[prefix_len]) {
            prefix_len++;
            next[i] = prefix_len;
            i++;
        } else {
            if (prefix_len != 0) {
                prefix_len = next[prefix_len - 1];
            } else {
                next[i] = 0;
                i++;
            }
        }
    }
    return next;
}

int KMPsearch(const string& text, const string& pattern) {
    vector<int> next = buildNext(pattern);
    int i = 0; // text 的索引
    int j = 0; // pattern 的索引
    int n = text.size();
    int m = pattern.size();

    while (i < n) {
        if (text[i] == pattern[j]) {
            i++;
            j++;
        }

        if (j == m) {
            return i - j; // 匹配成功,返回起始索引
        } else if (i < n && text[i] != pattern[j]) {
            if (j != 0) {
                j = next[j - 1];
            } else {
                i++;
            }
        }
    }
    return -1; // 未找到匹配
}

int main() {
    string text = "ababcabcabababd";
    string pattern = "ababd";
    int index = KMPsearch(text, pattern);

    if (index != -1) {
        cout << "Pattern found at index: " << index << endl;
    } else {
        cout << "Pattern not found" << endl;
    }

    return 0;
}

补充:前缀函数

此为字符串匹配的另一算法,通过简单转换即可转换为Kmp算法。

  • pi数组的定义:p[i]表示第i个前缀的最长匹配的真前、后缀的长度。
  • len=pi[len-1];这个解释和上述一样,就是寻找一个类似于回文的字符串。
vecotr<int>pi (str.size(),0);
for(int i=1;i<str.size();i++){
    int len=pi[i-1];
    while(len!=0&&str[i]!=str[len]){
        len=pi[len-1];
    }
    if(str[i]==str[len]){
        p[i]=len+1;
    }
}

标签:匹配,int,pattern,prefix,len,next,算法,杂乱,Kmp
From: https://blog.csdn.net/HeaoDng/article/details/141323926

相关文章

  • 实现strStr() —— KMP算法(包含next数组的优化)
    目录KMP算法KMP算法的应用前缀表最长公共前后缀为什么要使用前缀表如何计算前缀表前缀表和next数组时间复杂度分析例题28.实现strStr构造next数组 使用next数组来做匹配 前缀表统一减一C++代码实现前缀表(不减一)C++代码实现总结 拓展:next数组的优化 KMP算......
  • 常见的排序算法汇总(详解篇)
    目录排序的概念以及运用排序的概念1.插入排序1.1直接插入排序1.1.1 基本思想1.1.2代码实现直接插入排序的特征总结:1.1.3希尔排序(缩小增量排序)......
  • 迪杰斯特拉(Dijkstra)算法(C/C++)
    迪杰斯特拉(Dijkstra)算法是一种用于在加权图中找到单个源点到所有其他顶点的最短路径的算法。它是由荷兰计算机科学家艾兹格·迪科斯彻(EdsgerDijkstra)在1956年提出的。Dijkstra算法适用于处理带有非负权重的图。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法,每次遍历到始......
  • 2024年新SCI顶刊算法蛇鹭优化算法SBOA优化Transformer-LSTM模型的多变量时间序列预测
    matlabR2024a以上一、数据集二、2024年新SCI顶刊算法蛇鹭优化算法SBOA2024年,YFu受到自然界中鹭鹰生存行为启发,提出了鹭鹰优化算法(SecretaryBirdOptimizationAlgorithm,SBOA)。2.1算法思想SBOA生存需要不断地寻找猎物和躲避捕食者的追捕,探索阶段模拟鹭鹰捕食蛇,而......
  • Manacher 算法
    算法介绍\(\text{Manacher}\)算法(又名马拉车),是一种常用于处理回文字符串的算法。其代码量很小,却可以在\(O(n)\)的时间复杂度内处理问题算法思想和其他大多数算法一样,\(\text{Manacher}\)算法利用现有的信息获得下一部分的信息。经典例题:给定一个字符串\(s\)。求出其最长......
  • ACM算法——数学专题
    一、素数1、欧拉筛时间复杂度:\(O(n)\)constexprintN=1E6;std::vector<int>primes;std::vector<bool>st;voidinit(intn){st.assign(n+1,false);primes.clear();for(inti=2;i<=n;i++){if(!st[i]){pri......
  • 经典分治算法
    RT,主要介绍一些经典的分治算法CDQ分治经典人类智慧算法。三维偏序问题三维偏序是CDQ分治的一个经典应用,搭配树状数组可以在\(O(n\log^2n)\)的时间复杂度内解决问题。如果我们枚举每一个元素,然后枚举其他的元素的话,可以在\(O(n^2)\)的时间复杂度解决这个问题,但显然无法......
  • 粒子群算法和引力搜索算法的混合算法(PSOGSA)优化BP神经网络原理及matlab代码
    目录0引言1数学模型2模型对比3matlab代码3.1伪代码示意图3.2PSOGSA-BP4视频讲解0引言基于已发表智能算法文献研究,SeyedaliMirjalili等人在发现PSO的开发能力与GSA的探索能力有者较好结合性能,因此基于二者算法优势点提出混合算法PSOGSA。该算法主要利用PSO鸟......
  • 粒子群算法和引力搜索算法的混合算法(PSOGSA)优化长短期记忆神经网络原理及matlab代码
    目录0引言1数学模型2模型对比3matlab代码3.1伪代码示意图3.2PSOGSA-LSTM4视频讲解0引言基于已发表智能算法文献研究,SeyedaliMirjalili等人在发现PSO的开发能力与GSA的探索能力有者较好结合性能,因此基于二者算法优势点提出混合算法PSOGSA。该算法主要利用PSO......
  • 粒子群算法和引力搜索算法的混合算法(PSOGSA)优化支持向量机原理及matlab代码
    目录0引言1数学模型2模型对比3matlab代码3.1伪代码示意图3.2PSOGSA-SVM4视频讲解0引言基于已发表智能算法文献研究,SeyedaliMirjalili等人在发现PSO的开发能力与GSA的探索能力有者较好结合性能,因此基于二者算法优势点提出混合算法PSOGSA。该算法主要利用PSO......