KMP算法

作者: csuhan | 来源:发表于2019-03-05 14:14 被阅读0次

武大国重18年复试上机题目:KMP算法
祝自己顺利通过复试,加油!

字符串匹配是计算机基本任务之一,也是遥感数据处理中经常用到的。
Knuth-Morris-Pratt算法(简称KMP算法)是常用的算法之一。

部分匹配表

首先介绍下《部分匹配表》(Partial Match Table)的概念。



同时还有前缀和后缀的区别:


"部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABCDABD"为例,

  - "A"的前缀和后缀都为空集,共有元素的长度为0;

  - "AB"的前缀为[A],后缀为[B],共有元素的长度为0;

  - "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;

  - "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

  - "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;

  - "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;

  - "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

KMP算法

对于原字符串与搜索词,首先比较第一位,因为两者不匹配,所以原字符串后移一位。



因为B与A不匹配,继续后移。



现在出现了一个匹配字符,接着比较

两者还是相同。继续比较,直到出现不相同的字符为止。


image.png

自然状态下,我们可以通过暴力破解,采用两层循环进行匹配,但效率太低。
事实上,当空格与D不匹配时,前面6个已经匹配了,不需要返回搜索,因此我们可以记录这个信息,直接跳过前6个字符。


因此,其大致流程如下:

  1. 原字符串与搜索词都从第一个字符开始匹配,若无匹配,则原字符串跳下一个;若有匹配,则继续匹配
  2. 确定两者匹配的字符串数,若未完全匹配,则记录已匹配个数;若完全匹配,则记录匹配位置
  3. 无论是否完全匹配,都将原字符串跳到上次匹配的末尾,继续匹配,直到整个原字符串匹配完毕。其中,跳跃的步数 = 已匹配的字数 - 其部分匹配值

编程实现

//KMP算法的实现

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>

using namespace std;


int main()
{
    string ts, ps; //ts:待匹配串,ps:模式串
    cin >> ts >> ps;

    //计算next数组(部分匹配表)
    vector<int> next(ps.size(), 0); //next数组初始化
    for (size_t i = 1; i < ps.size(); i++)
    {
        string substr = ps.substr(0, i);//子串
        for (size_t j = 1; j < substr.size()-1; j++)
        {
            string strp = substr.substr(0, j);//前缀
            string stre = substr.substr(substr.size() - j, j);//后缀
            if (strp == stre)next[i - 1] = j;
        }
    }

    //KMP搜索
    for (size_t i = 0; i < ts.size(); i++)
    {//遍历ts
        for (size_t j = 0; j < ps.size(); j++)
        {//遍历ps
            if (ts[i + j] != ps[j]) break; //无匹配时跳出
            if (j + 1 == ps.size()) {//匹配长度为ps长度说明匹配到了
                cout <<"字符已匹配在:"<< i + 1 << '\t' << endl;
                continue;
            }
            else {
                i += next[j];
            }
        }
    }

    system("pause");
    return 0;
}

本文参考:
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
https://blog.csdn.net/u011197534/article/details/78385547

相关文章

  • KMP 专题整理

    KMP 学习记录 kuangbin专题十六——KMP KMP 学习总结 朴素 KMP 算法 拓展 KMP 算法(E...

  • 对KMP算法的一些理解

    最近学到KMP算法,下面讲讲对KMP算法的一些个人理解,希望对大家有帮助! 对于KMP算法的理解: 整个KMP算法...

  • KMP算法文章合集

    字符串的查找:朴素查找算法和KMP算法 暴力匹配算法与KMP算法(串的匹配) 字符串查找算法BF和KMP 字符串匹...

  • 串的模式匹配算法

    KMP算法 算法匹配

  • 问答|KMP算法学习笔记

    问题 目录KMP是什么,做什么用的KMP算法的高效体现在哪如何KMP算法的next数组KMP的代码KMP的时间复杂...

  • KMP算法——寻找子串位置

    KMP算法——寻找子串位置 1、KMP算法简介: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J....

  • 字符串匹配 - KMP算法

    前面我们介绍非常高效的 BM 算法,今天我们介绍另一个非常出名且高效的 KMP 算法。 KMP 算法思想 KMP ...

  • KMP算法及优化

    转载请注明出处: KMP算法及优化 今天看到同学在复习数据结构书上的KMP算法,忽然发觉自己又把KMP算法忘掉了,...

  • KMP算法(字符串匹配问题)

    一、是什么? 注意,是KMP算法,不是MMP哈,我没有骂人。KMP算法是用来做字符串匹配的,除了KMP算法分,还有...

  • KMP算法

    KMP算法

网友评论

      本文标题:KMP算法

      本文链接:https://www.haomeiwen.com/subject/qqgnuqtx.html