数据结构和算法笔记6:KMP算法

KMP(Knuth-Morris-Pratt)算法是一种字符串匹配算法,用于在一个文本串中查找一个模式串的出现位置。它的主要优势在于在匹配过程中避免了不必要的回溯,提高了匹配效率。

KMP算法的核心思想是利用已经匹配过的信息,避免在模式串与文本串匹配过程中进行不必要的回溯。它通过构建一个部分匹配表(也称为失配函数),记录模式串中每个位置的最长可匹配前缀和后缀的长度,从而在匹配过程中通过查表来决定下一次匹配的位置。相关原理建议看文后的参考链接,讲得非常细致,可以先看3,再看1和2。

下面是KMP算法的代码实现(使用C++语言),下面是用KMP算法找寻text串中第一个pattern串的索引位置的代码:

cpp 复制代码
#include <iostream>
#include <vector>

using namespace std;

vector<int> buildPartialMatchTable(const string& pattern) {
    int m = pattern.length();
    vector<int> next(m, 0);
    int i = 1, j = 0;

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

int kmpSearch(const string& text, const string& pattern) {
    int n = text.length();
    int m = pattern.length();
    if (m == 0) {
        return 0;
    }
    if (n == 0) {
        return -1;
    }
    
    vector<int> next = buildPartialMatchTable(pattern);
    int i = 0, j = 0;
    while (i < n) {
        if (text[i] == pattern[j]) {
            i++;
            j++;
            if (j == m) {
                return i - j;
            }
        } else {
            if (j != 0) {
                j = next[j - 1];
            } else {
                i++;
            }
        }
    }
    return -1;
}

int main() {
    string text = "sadbutsad";
    string pattern = "sad";
    
    int index = kmpSearch(text, pattern);
    if (index != -1) {
        cout << "Pattern found at index " << index << endl;
    } else {
        cout << "Pattern not found" << endl;
    }
    
    return 0;
}

上面是用while循环写的逻辑,可以使用for循环更简洁点:

cpp 复制代码
#include <iostream>
#include <vector>

using namespace std;

vector<int> buildPartialMatchTable(const string& pattern) {
    int m = pattern.length();
    vector<int> next(m, 0);
    int i = 1, j = 0;
    for (int i = 1; i < m; ++i)
    {
    	while (j > 0 && pattern[i] != pattern[j])
    		j = next[j - 1];
    	if (pattern[i] == pattern[j])
			++j;
		next[i] = j;
    }
    return next;
}

int kmpSearch(const string& text, const string& pattern) {
    int n = text.length();
    int m = pattern.length();
    if (m == 0) {
        return 0;
    }
    if (n == 0) {
        return -1;
    }
    
    vector<int> next = buildPartialMatchTable(pattern);
    int i = 0, j = 0;
    for (int i = 0; i < n; ++i)
    {
		while (i > 0 && text[i] != pattern[j])
			j = next[j - 1];
		if (text[i] == pattern[j])
			++j;
		if (j == m)
			return i - m + 1;
	}
    return -1;
}

int main() {
    string text = "sadbutsad";
    string pattern = "sad";
    
    int index = kmpSearch(text, pattern);
    if (index != -1) {
        cout << "Pattern found at index " << index << endl;
    } else {
        cout << "Pattern not found" << endl;
    }
    
    return 0;
}

输出:

KMP算法力扣相关的题目:

28. 找出字符串中第一个匹配项的下标

相关参考:

  1. 代码随想录-28. 实现 strStr()
  2. 【宫水三叶】简单题学 KMP 算法
  3. 灵茶山艾府的知乎回答:如何更好地理解和掌握 KMP 算法?
相关推荐
荼蘼21 分钟前
基于 KNN 算法的手写数字识别项目实践
人工智能·算法·机器学习
Yuroo zhou42 分钟前
IMU的精度对无人机姿态控制意味着什么?
单片机·嵌入式硬件·算法·无人机·嵌入式实时数据库
致***锌1 小时前
上证50ETF期权的交易时间是什么时候?
笔记
thginWalker1 小时前
图解网络-小林coding笔记(持续更新)
网络·笔记
jackzhuoa1 小时前
java小白闯关记第一天(两个数相加)
java·算法·蓝桥杯·期末
Codeking__2 小时前
链表算法综合——重排链表
网络·算法·链表
minji...3 小时前
数据结构 堆(4)---TOP-K问题
java·数据结构·算法
草堂春睡足3 小时前
【Datawhale AI夏令营】科大讯飞AI大赛(大模型技术)/夏令营:让AI理解列车排期表
人工智能·笔记
AI_Keymaker3 小时前
一句话生成3D世界:腾讯开源混元3D模型
算法
Leon_vibs3 小时前
当 think 遇上 tool:深入解析 Agent 的规划之道
算法