kmp算法是改进后的字符匹配算法,它与bf算法的区别是,每次从串与主串匹配失败后,从串与主串匹配的位置不同。

下面具体说下这两种算法的区别:

主串:BABCDABABCDABCED

从串:ABCDABCED

BF算法:

第一步:

B A B C D A B A B C D A B C E D
A                              

从主串的第一个字符位置开始与从串第一个字符位置进行匹配,匹配失败

第二步:

B A B C D A B A B C D A B C E D
  A B C D A B C                

从主串的第二个字符位置开始与从串第一个字符位置进行匹配,匹配失败

第三步:

B A B C D A B A B C D A B C E D
    A                          

从主串的第三个字符位置开始与从串第一个字符位置进行匹配,匹配失败

...........

第七步:

B A B C D A B A B C D A B C E D
            A                  

从主串的第七个字符位置开始于从串第一个字符位置进行匹配,匹配失败

第八步:

B A B C D A B A B C D A B C E D
              A B C D A B C E D

匹配成功,这个就是BF算法,每次匹配失败后要从主串的下一个字符位置与从串的第一个字符接着进行匹配。

kmp算法:

第一步:

B A B C D A B A B C D A B C E D
A                              

主串与从串的第一个字符不匹配

第二步:

B A B C D A B A B C D A B C E D

A B C D A B C







这两步和bf一样

第三步:

B A B C D A B A B C D A B C E D





A B C







这里就和bf不一样了,其原因就是从串中字符有相同的一部分(AB),这里先知道区别,待会我会说它的实现过程


第四步:

B A B C D A B A B C D A B C E D
              A B C D A B C E D

如果看不懂的话,下面会讲清楚,然后根据程序找下标就可以知道原因了。

kmp算法分两部分:①next数组(kmp算法的核心)

②字符串的匹配

在讲解next数组时,顺便把前缀和后缀的知识也说了。

比如上面的从串:ABCDABCED(前缀是从第一个字符数,但后缀不是倒着数,它也是顺着数,看下面的写法吧)

第一个字符前,它没有串,所以没有前缀和后缀,则它也没有最长长度,我把它的长度初始化为0。

第二个字符前,它的串是A,前缀和后缀是不能包含串本身,所以它没有前缀和后缀,长度为0。

第三个字符前,它的串是AB,前缀是A,后缀是B,不匹配,长度为0。

第四个字符前,它的串是ABC,第一种,前缀是A,后缀是C,不匹配,长度为0,

第二种,前缀是AB,后缀是BC,不匹配,长度为0,

所以最长长度为0。

第五个字符前,它的串是ABCD,第一种,前缀是A,后缀是D,不匹配,长度为0,

第二种,前缀是AB,后缀是CD,不匹配,长度为0,

第三种,前缀是ABC,后缀是BCD,不匹配,长度为0,

所以最长长度为0。

第六个字符前,它的串是ABCDA,第一种,前缀是A,后缀是A,匹配,长度为1,

第二种,前缀是AB,后缀是DA,不匹配,长度为0,

第三种,前缀是ABC,后缀是CDA,不匹配,长度为0,

第四种,前缀是ABCD,后缀是BCDA,不匹配,长度为0,

所以最长长度为1。

第七个字符前,它的串是ABCDAB,第一种,前缀是A,后缀是B,不匹配,长度为0,

第二种,前缀是AB,后缀是AB,匹配,长度为2,

第三种,前缀是ABC,后缀是DAB,不匹配,长度为0,

第四种,前缀是ABCD,后缀是CDAB,不匹配,长度为0,

第五种,前缀是ABCDA,后缀是BCDAB, 不匹配,长度为0,

所以最长长度为2。

第八个字符前,它的串是ABCDABC,第一种,前缀是A,后缀是C,不匹配,长度为0,

第二种,前缀是AB,后缀是BC,不匹配,长度为0,

第三种,前缀是ABC,后缀是ABC,匹配,长度为3,

第四种,前缀是ABCD,后缀是DABC,不匹配,长度为0,

第五种,前缀是ABCDA,后缀是CDABC,不匹配,长度为0,

第六种,前缀是ABCDAB,后缀是BCDABC,不匹配,长度为0,

所以最长长度为3。

第九个字符前,它的串是ABCDABCE,第一种,前缀是A,后缀是E,不匹配,长度为0,

第二种,前缀是AB,后缀是CE,不匹配,长度为0,

第三种,前缀是ABC,后缀是BCE,不匹配,长度为0,

第四种,前缀是ABCD,后缀是ABCE,不匹配,长度为0,

第五种,前缀是ABCDA,后缀是DABCE,不匹配,长度为0,

第六种,前缀是ABCDAB,后缀是CDABCE,不匹配,长度为0,

第七种,前缀是ABCDABC,后缀是BCDABCE,不匹配,长度为0,

所以最长长度为0。

然后根据我们求出来的最长长度,就能绘制出next表了,

下标 1 2 3 4 5 6 7 8 9
从串 A B C D A B C E D
next 0 0 0 0 0 1 2 3 0
可能别人的next和kmp和我写的不一样,不过我就是这么理解的,如果哪里错了,大家可以提出来
当然这个next数组也可以改进的,大家想一想,上面在比较bf与kmp算法是,kmp的第三步是不是多余了,为什么呢,因为第二步的ABCDABC中的第二个C与主串中的A不匹配,第三步还是ABC,这里面的C肯定也与A不匹配,所以也就有了next数组的改进,怎么改进呢,很简单,只要相等时候,让它等于前面那个一样字符的next数组下标就可以了,看表格
下标 1 2 3 4 5 6 7 8 9
从串 A B C D A B C E D
next 0 0 0 0 0 0 0 3 0

第二个B与第一个B的next值一样为0,第二个C与第一个C的next值一样为0。

这就是next数组及其改进后的next数组。

next数组程序:

void Get_next(int *next, string s2)
{
    int i = 1;
    int j = 0;
    next[i] = 0;
    while(i <= s2.length())
    {
        if(j == 0 || s2[i - 1] == s2[j - 1])
        {
            i++;
            j++;
            if(s2[i - 1] == s2[j - 1])
                next[i] = next[j];
            else
                next[i] = j - 1;
        }
        else
            j = next[j];
    }
}

如果你理解了next数组的求值方法,根据bf算法的思路应该可以写出kmp字符匹配函数,

下面是kmp算法的总体程序:

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

//求next数组下标
void Get_next(int *next, string s2)
{
    int i = 1;
    int j = 0;
    next[i] = 0;
    while(i <= s2.length())
    {
        if(j == 0 || s2[i - 1] == s2[j - 1])
        {
            i++;
            j++;
            if(s2[i - 1] == s2[j - 1])
                next[i] = next[j];
            else
                next[i] = j - 1;
        }
        else
            j = next[j];
    }
//    for(int k = 1; k < 10; k++)
//        cout << next[k] << endl;
}
//匹配部分
int kmp(string s1, string s2, int pos)
{
    int next[100];
    Get_next(next, s2);
    int i = 0;
    int j = 0;
    while(i < s1.length() && j < s2.length())
    {
        if(j == 0 || s1[i] == s2[j])
        {
            i++;
            j++;
        }
        else
        {
            j = next[j + 1];
        }
    }
    if(j >= s2.length())
        return i - s2.length();
    return -1;
}
int main()
{
    string s1= "babcdababcdabced";
    string s2 = "abcdabced";
    int pos;
    cin >> pos;
    cout << kmp(s1, s2 ,pos) << endl;
    return 0;
}

本程序只是个人的想法和思路,若有错误还请大家提出,若有不明白的地方,请在下面评论,谢谢大家啦!

对了,我的算法应该存在问题,希望多多指出。

算法 kmp算法的更多相关文章

  1. 数据结构与算法--KMP算法查找子字符串

    数据结构与算法--KMP算法查找子字符串 部分内容和图片来自这三篇文章: 这篇文章.这篇文章.还有这篇他们写得非常棒.结合他们的解释和自己的理解,完成了本文. 上一节介绍了暴力法查找子字符串,同时也发 ...

  2. 经典算法 KMP算法详解

    内容: 1.问题引入 2.暴力求解方法 3.优化方法 4.KMP算法 1.问题引入 原始问题: 对于一个字符串 str (长度为N)和另一个字符串 match (长度为M),如果 match 是 st ...

  3. 笔记-算法-KMP算法

    笔记-算法-KMP算法 1.      KMP算法 KMP算法是一种改进的字符串匹配算法,KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一 ...

  4. 值得花费一周研究的算法 -- KMP算法(indexOf)

    KMP算法是由三个科学家(kmp分别是他们名字的首字母)创造出来的一种字符串匹配算法. 所解决的问题: 求文本字符串text内寻找第一次出现字符串s的下标,若未出现返回-1. 例如 text : &q ...

  5. [C++] [算法] KMP算法

    KMP串匹配算法是一个经典的算法. 传统BF算法是传统的字符串匹配算法.很好理解.叶实现.但时间复杂度太高. 本文将从字符串模式字符串被称为.为了匹配字符串被称为主弦. KMP配时能够少移动从串的位置 ...

  6. 程序员必会算法-KMP算法

    KMP算法是一种优秀的字符串匹配算法,字符串匹配的常规算法是一步一步进行移位和比较操作,直至找到完全相匹配的字符串. 下面通过一个例子,为大家仔细说明KMP算法的使用和思路: 问题: 在字符串“DEA ...

  7. BF算法 + KMP算法

    准备: 字符串比大小:比的就是字符串里每个字符的ASCII码的大小.(其实这样的比较没有多大的意义,我们关心的是字符串是否相等,即匹配等) 字符串的存储结构:同线性表(顺序存储+链式存储) 顺序存储结 ...

  8. 图解算法——KMP算法

    KMP算法 解决的是包,含问题. Str1中是否包含str2,如果包含,则返回子串开始位置.否则返回-1. 示例1: Str1:abcd123def Str2:123d 暴力法: 从str1的第一个字 ...

  9. 字符串匹配算法——KMP算法

    处理字符串的过程中,难免会遇到字符匹配的问题.常用的字符匹配方法 1. 朴素模式匹配算法(Brute-Force算法) 求子串位置的定位函数Index( S, T, pos). 模式匹配:子串的定位操 ...

随机推荐

  1. 列举spark所有算子

    一.RDD概述      1.什么是RDD           RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可 ...

  2. windows开发各种dll缺失

    推荐使用 depend这个工具,非常好用 http://www.dependencywalker.com/ 打开对应的文件,就能看到缺失了哪些dll 感谢博主: https://blog.csdn.n ...

  3. Jmeter安装使用

    Jmeter的安装与使用 首先,安装Jmeter需要JDK https://www.oracle.com/technetwork/java/javase/downloads/index.html 配置 ...

  4. 关于mysql 表导入数据

    一.实验准备: 1.实验设备:Dell laptop 7559; 2.实验环境:windows 10操作系统; 3.数据库版本:mysql 8.0; 二.实验目的: 1.将一个宠物表pet.txt文件 ...

  5. python--面向过程编程与面向对象编程

    面向过程 面向过程: 核心就是过程二字,过程指的是解决问题的步骤,设计一条流水线,机械式的思维方式. 优点: 复杂的问题流程化,进而简单化. 缺点: 可扩展性差. 面向对象 面向对象: 核心就是对象二 ...

  6. Win10 安装SqlServer2012 无法访问数据库

    win10系统,安装好vs2017,sqlserver2012, 在abp     执行 Update-Database 会出错 具体解决办法是SqlServer2012的1433端口没打开. 打开办 ...

  7. linux随机字符串

    pwgen  -s 32 1 openssl passwd -salt openssl rand -base64 32 openssl rand -hex 100

  8. jmeter(一)

      jmeter简介   Apache jmeter是Apache组织开发的基于java的压力测试工具   与LR功能基本相同,根据用户数来选择用哪个更合适   为什么要做压力测试? 了解被测系统一般 ...

  9. 在树莓派3B、Ubuntu 18.04关闭板载Wifi、蓝牙

    树莓派没有传统的BIOS设置界面,文件/boot/firmware/config.txt就相当一个BIOS设置.这里是config.txt的详细文档:https://github.com/raspbe ...

  10. 【C++】纯C++实现http打开网页下载内容的功能

    #include "stdafx.h" #include <windows.h> #include <iostream> #include "Wi ...