美文网首页
使用kmp算法查找子串

使用kmp算法查找子串

作者: echo_a5fe | 来源:发表于2019-07-10 16:26 被阅读0次

问题:在字符串S中查找Sub

边界条件:S长度或者Sub长度为0,或者Sub长度大于S长度,返回-1;

KMP算法

失效函数f(i)

假如目标串是Sub,则失效函数f(i)表示既是Sub(0,i)的真前缀又是Sub(0,i)的后缀的最长串的长度,通俗地说就是前后相等的子串长度。

有时候也被叫做next数组,因为它代表了如果匹配失败下一次将从哪个开始匹配

举一个书本中的例子,求ababaa的失效函数。

失效函数自变量 子串 首尾相等的子串 失效函数值
0 a 0
1 ab 0
2 aba a 1
3 abab ab 2
4 ababa aba 3
5 ababaa a 1

当使用编程语言实现时,求值思想是在上一个失效函数值的基础上求出当前所求的失效值。这个是我从编译原理第二版上看到的方法,比较简洁明了。继续使用上面的例子,对ababaa求失效函数,根据定义我们可以直接得出f(0) 为0。

在求其他位置的效值的过程中,我们维护两个下标:一个是当前位置的下标,一个上一个位置的失效值。

为什么要保存这两个下标呢?

1.我们通过当前位置下标取得要比较的字符,并将失效值写入对应的地方。

2.通过观察可以发现,假如上一个位置的失效函数值为i,当前位置为j,那么在i和j之前的字符都已经被对比且为相等了,如果i和j对比不相等,直接把i变成i-1处的失效函数值,假设是q,那么q和j之前的字符也肯定是比对且为相等的了,这就是失效函数的神奇之处。

文字描述不容易理解,下面通过画图来描述

image

用c++实现


vector<int> next(const string & S )
{
    vector<int> f(S.length());  //已经知道需要求的值的个数
    int i = 0;
    f[0]= 0; //第一个肯定是0
    for (int j = 1; j < S.length(); j++) {
        while (i > 0 & S[i] != S[j]) i = f[i-1];  //如果当前要对比的字符还是不相等且没回退到第一个则一直回退到前一个的失效函数值处
        if (S[i] == S[j]) {
            ++ i;
            f[j] = i;
        }else {
            f[j]= 0;
        }
    }
    return f;
}

使用求得的失效函数

使用KMP算法求子串位置,查找到则返回-1.
在前面的求失效函数的过程中我们已经利用了失效函数了,如果没理解可以多看几遍,这个地方有点绕。原理是当对比到第j个字符发现不相等时,前面的j-1个字符其实已经是相等的了,接下来要做的就是利用这一部分信息来避免回溯。

对比发现不相等的情况以及处理

书中使用的术语是“滑动”,效果如图


根据上一位置失效值移动

将上述思想使用c++表达,未做错误处理,因为这篇文章的目的是理清思路。

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

}

相关文章

  • KMP算法文章合集

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

  • 使用kmp算法查找子串

    问题:在字符串S中查找Sub 边界条件:S长度或者Sub长度为0,或者Sub长度大于S长度,返回-1; KMP算法...

  • 算法(2)KMP算法

    1.0 问题描述 实现KMP算法查找字符串。 2.0 问题分析 “KMP算法”是对字符串查找“简单算法”的优化。 ...

  • 子字符串查找(1)

    一、定义 本文主要介绍子字符串查找的各类常用算法,如朴素匹配算法(暴力查找)、KMP算法、BM算法等。各类匹配算法...

  • JavaScript 二分查找 & KMP 算法

    KMP 查找 Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串 str1...

  • 字符串匹配KMP算法

    假设我们的字符串母串是,子串是,我们想找到子串在母串中出现的位置并统计总的出现次数,可以使用KMP算法。KMP算法...

  • KMP算法

    KMP算法用于子字符串查找(匹配)。 KMP是三个科学家[Knuth-Morris-Pratt]发明的,旨在对暴力...

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

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

  • iOS-字符串查找

    字符串查找通常有四种方式,暴力查找,KMP查找,BoyerMoore查找以及RabinKarp算法查找,查找最简单...

  • 数据结构之kmp算法

    Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串...

网友评论

      本文标题:使用kmp算法查找子串

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