KMP 算法简单解释

KMP 算法简单解释

? 讲KMP算法,离不开BF,实际上,KMP就是BF升级版,主要流程和BF一样,就是在削除回溯上花了点功夫,利用Next数组来削除

<( ̄︶ ̄)[GO!]

1. 先看看BF算法(暴力破解)

int Brute_force_1(const char *S, const char *T)
{
    if (!S || !T)
        return -1;
    int lenS = strlen(S);
    int lenT = strlen(T);
    int i = 0;              //主串下标索引
    int j = 0;              //子串下标索引
    while(i < lenS && j < lenT)
    {
        if (S[i] == T[j])   //如果相等一直继续往下匹配
            ++i,++j;
        else                //不相等i和j开始回溯
        {
            i = i-j+1;
            j = 0;
        }
    }
    if (j == lenT)
        return i - j;
    return -1;
}

? BF算法有几种不同实现,但最终思想都是一样的,以下就是另一个BF实现

int Brute_force_2(const char *S, const char *T)
{
    if (!S || !T)
        return -1;
    int lenS = strlen(S);
    int lenT = strlen(T);
    for (int i = 0; i <= lenS - lenT; ++i)
    {
        int k = i, j = 0;
        while (k < lenS && j < lenT && S[k] == T[j])
        {
            ++j;
            ++k;
        }
        if (j == lenT)
            return i; //说明匹配到了
    }
    return -1;
}

? 你完全可以根据自己的理解写出BF算法,但在这里,为了BF和KMP统一,我们还是采用第一种实现,即容易看出回溯操作的实现

2. Next[]数组

? 事实上,书上的next数组生成算法是经过优化后的算法,比较难懂,但你完全可以按照自己的理解做一个

? 注意:Next[]数组只是在KMP中字符串匹配失败时使用的

void GetNext(int Next[], char *str)
{
    assert(str!=NULL);
    int len = strlen(str);
    if(len>1)Next[0]=0;
//其实Next[0]等于0或者等于-1效果没什么影响,
//因为在KMP中不匹配时判断是不是第一个字符不匹配用用的是j==0;-----if (j==0||Next[j]==0),
    if(len>2)Next[1]=0;
//Next[]等于0时说明需要讲i回溯到子串头的下一个位置(i=i-j+1);
//此时j也回到子串头位置(j=0)
    for(int i=2;i<len;++i)
    {
        for(int j=i-1;j>0;--j)
        {
            if(!strncmp(&str[0],&str[i-j],j))
            {
                Next[i]=j;break;        //找到最大重复子子串(子串中的子串)
//Next[]为其他值则i不变,讲j回溯到Next[j]的位置(j=Next[j])
            }
            else Next[i]=0;
        }
    }
}

? 这个时间复杂度要比书上的方法高很多,但好理解,真实的反映了Next数组的本质。

3.KMP

int KMP(const char *S, const char *T, const int *Next)
{
    if (!S || !T||!Next)
        return -1;
    int lenS = strlen(S);
    int lenT = strlen(T);
    int i = 0;              //主串下标索引
    int j = 0;              //子串下标索引
    while(i < lenS && j < lenT)
    {
        if (S[i] == T[j]) ++i,++j;  //若相等则继续匹配下一个字符
        else        //不相等则回溯
        {
            //(当j==0时,即第一个字符不匹配,和Next[j]==0时事实上与BF算法相同)
            if (j==0||Next[j]==0)
            {
                i = i-j+1;
                j = 0;
            }
            else j = Next[j];//主串i位置不变,讲子串下标索引挪到Next[j]的位置
        }
    }
    if (j == lenT)
        return i - j;
    return -1;
}

? 这个回溯时的操作实际上是把两种情况合成一种,拆开后就是下面的,就是生成next数组那块三种情况

while (i < lenS && j < lenT)
{
    if (S[i] == T[j])
        ++i, ++j;
    else
    {
        if (j == 0)
        {
            ++i; //等价于i = i-0+1;j本身就等于0
        }
        else if (Next[j] == 0)
        {
            i = i - j + 1;
            j = 0;
        }
        else
        {
            j = Next[j];
        }
    }
}

总结

? 其实核心就在与本文第一句话的理解。书上的next数组的生成很难懂,加油理解中。。。(? ?_?)?

原文地址:https://www.cnblogs.com/starrys/p/11625840.html

时间: 2024-08-09 14:49:25

KMP 算法简单解释的相关文章

KMP算法具体解释(贴链接)

------------------------------------------------------------------------------------------------------------------------------------------------------ 欢迎光临天资小屋:http://user.qzone.qq.com/593830943/main --------------------------------------------------

KMP算法具体解释(转)

作者:July. 出处:http://blog.csdn.net/v_JULY_v/. 引记 此前一天,一位MS的朋友邀我一起去与他讨论高速排序,红黑树,字典树,B树.后缀树,包含KMP算法,只有在解说KMP算法的时候,言语磕磕碰碰,我想,原因有二:1.博客内的东西不常回想,忘了不少:2.便是我对KMP算法的理解还不够彻底,自不用说解说自如,运用自如了.所以,特再写本篇文章.因为此前,个人已经写过关于KMP算法的两篇文章,所以,本文名为:KMP算法之总结篇. 本文分为例如以下六个部分: 第一部分

KMP算法简单回顾

前言 虽从事企业应用的设计与开发,闲暇之时,还是偶尔涉猎数学和算法的东西,本篇根据个人角度来写一点关于KMP串匹配的东西,一方面向伟人致敬,另一方面也是练练手,头脑风暴.我在自娱自乐,路过的朋友别太认真,嘿 背景 目标串: T(1…..n) 模式串: P(1…..m) 输出:搜索P在T中的位置 s,令 T(s…s+m-1) === P(1…m) 例如: a g c t a g c a g c t a g c t g中查找a g c t g 返回 12(从1计数) 资料 资料太多了,我在此不准备进

KMP算法详解(图示+代码)

算法过程非常绕,不要企图一次就能看明白,多尝试就会明白一些.下面试图用比较直观的方法解释这个算法,对KMP算法的解释如下: 1. 首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较.因为B与A不匹配,所以搜索词后移一位. 2. 因为B与A不匹配,搜索词再往后移. 3. 就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止. 4. 接着比较字符串和搜索词的下一个字符,还是相同. 5. 直到字

KMP算法变形——对链表的处理

KMP算法简单粗暴的代码,严密的逻辑,初学的时候,真的很难搞懂,不过曾力胜老师这周出的模式串匹配的变形题目,让我反思了一下KMP算法,昨天晚上写出了链表形式,也算是进步吧.昨天太急,没来得及记录,今天补充起来. /* Name: KMP之链表写法 Date :2015/3/29 Write by:杨领 */ #include<stdio.h> #include<stdlib.h> typedef struct node { int data;//数据域 struct node *n

HDProblem-2203亲和数(KMP算法)

1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define N 100005 5 char s1[2*N],s2[N]; 6 int next[N],l1,l2; 7 8 void get_next(char *str,int len) 9 { 10 int i=-1,j=0; 11 next[0]=-1; //注意给next[0]赋初值 12 len=strlen(str); 13 i

字符串匹配KMP算法C++代码实现

看到了一篇关于<字符串匹配的KMP算法>(见下文)的介绍,地址:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html,这篇博客对KMP算法的解释很清晰,但缺点是没有代码的实现.所以本人根据这位大神的思路写了一下算法的C++实现. C++代码如下: #include <iostream> #include<string.h> using namesp

字符串匹配(KMP 算法 含代码)

主要是针对字符串的匹配算法进行解说 有关字符串的基本知识 传统的串匹配法 模式匹配的一种改进算法KMP算法 网上一比較易懂的解说 小样例 1计算next 2计算nextval 代码 有关字符串的基本知识 串(string或字符串)是由零个或多个字符组成的有限序列,一般记为 当中s是串的名,用单引號括起来的字符序列是串的值:ai(1<=i<=n)能够是字母.数值或其它字符.串中字符的数组 n称为串的长度.零个字符的串称为空串,它的长度为0 串中随意个连续的字符组成的子序列称为该串的子串. 包括子

KMP算法的next[]数组通俗解释

我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度. 当然我们可以看到这个算法针对的是子串有对称属性,如果有对称属性,那么就需要向前查找是否有可以再次匹配的内容. 在KMP算法中有个数组,叫做前缀数组,也有的叫next数组,每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符,当然它描述的也是子串的对称程度,程度越高,值越大,当然之前可能出现再匹配的机会就更大.