左神讲解基础算法--kmp算法

主要解决问题:包含问题。

例如:

str1: abc123def

str2:123d

str1中是否包含有str2这个字串。(注意字串与子序列区别)

子序列:可以连续也可以不连续

子数组/子串:必须是连续的。

好了废话不多说了,我们上正菜。首先,想了解kmp的加速过程,要先知道一个数组叫next数组,这个数组中存放了str2中每个字符的前缀和后缀相匹配的最长长度(注意是前缀和后缀的最长的那个匹配长度)。什么意思呢?举例说下:

图中str2中下标为0的字符它的前缀和后缀长度都是0,(记住前缀和后缀是不包含本身的这个字符的)在这里我们人为规定它的next数组值为-1,下标为1的字符的最长前缀长度是1,后缀也是1,但是我们不能包含这个前后缀字符串是同一个字符串的情况所以我们给它的next数组值为0,下标为2的字符的前缀是“a” “ab”后缀是“b”,“ab”又因为“ab”“ab”是同一字符串,所以不合格,“a”与“b”不相同,所以next[2]=0;str2[3]的前缀是“a”

“ab””aba”后缀是  “a””ba””aba”,同理”aba“不合格,所以相同字符串只有”a“  所以 next[3]=1;

按照上面的步骤,给next数组依次赋值。

next数组知道值之后我们就要利用next数组进行加速求解字串匹配问题例如:

假设str1和str2分别从i位置和零位置一直匹配到x和y位置,(str1的长度并不是i到x,str2也不代表y就是结尾)x和y位置没有匹配上,如果是暴力解法就需要从i+1开始继续和str2[0]开始匹配,但是有了next数组我们不用这样做,因为str1和str2一直到x和y之前都相同所以x和y位置的最长前缀和最长后缀的数值是一样的所以利用y位置的next数组值找到与前缀相匹配的最长后缀位置,我们从图中str1[j]和str2[0]开始匹配,同理因为str1[j]到str2[x-1]与str2的str2[0]到str2[z-1]相同所以直接匹配str2[z]和str1[x]是否匹配。

证明:

假设 :

假设如果我们存在k位置到x位置与str2匹配,那就意味者在x位置的next数组求出来的前缀和后缀匹配的最长字符串就不是j到x-1和i到s-1了,这与我们的next数组的规则不符,所以我们直接可以证明i+1位置到j-1位置没有可能与str2匹配的子串,这就是kmp的加速过程。好了,说了这么多有的人可能听蒙了。直接上代码吧!

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
void Nextarrary(int *(&next),string *str)
{
    if (str->length() == 1)
    {
        next[0] = -1;
        return;
    }
    next[0] = -1;
    next[1] = 0;
    int len = str->length();
    int i = 2;
    int cn = 0;
    while(i<len)
    {
        if (str[i - 1] == str[cn])
            next[i++] = ++cn;
        else if (cn > 0)
            cn = next[cn];
        else
            next[i++] = 0;
    }
}
int GetStrmatch(string str1, string str2)
{
    if (str1.length() == 0 || str2.length() == 0)
        return -1;
    int *next = new int[str2.length()];
    int len1 = str1.length();
    int len2 = str2.length();
    Nextarrary(next, &str2);
    int i = 0;
    int end = 0;
    while (i < len1&&end < len2)
    {
        if (str1.at(i) == str2.at(end))
        {
            end++; i++;
        }
        else if (next[end] == -1)
            i++;
        else
            end = next[end];
    }
    delete[] next;
    next = NULL;
    return ((end == len2) ? i-end : -1);
}

以上是代码,小编是自己学习后的总结,有不对的地方,请大佬多多指出!

原文地址:https://www.cnblogs.com/ycw1024/p/11247455.html

时间: 2024-08-04 07:19:02

左神讲解基础算法--kmp算法的相关文章

HDU1711 最基础的kmp算法

Problem Description Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], ...... , a[K + M - 1]

菜鸟学算法-KMP算法

一. KMP算法 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,简称KMP算法.KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息. 二. KMP算法的意义 先举一个简单模式匹配的例子,给定字符串T=“abababca”,S=“bacbababaabcbab”,判断T是否是S的子串,如果用暴力扫描的话,就是拿着T字符串从

[C++] [算法] KMP算法

在虚拟机上测评了下MySQL 和 PostgreSQL 的各种LOAD FILE方式以及时间. 因为是虚拟机上的测评,所以时间只做参考,不要太较真, 看看就好了.MySQL 工具:    1. 自带mysqlimport工具.    2. 命令行 load data infile ...    3. 利用mysql-connector-python Driver来写的脚本. PostgreSQL 工具:    1. pgloader 第三方工具.    2. 命令行 copy ... from

算法 - KMP算法

1 解决问题 从一个字符串中查找子串,如果存在返回字串在字符串中的位置. 示例: 字符串(T):"BBC ABCDAB ABCDABCDABDE" 子串( P):"ABCDABD" 通过算法查找字串P在字符串T中的位置为15(从0开始). 2 暴力算法 思路: 循环T,从T的每个字符开始子字串P匹配. 代码: int strstr(char iTarget[], int iTLen, char iPattern[], int iPLen) { for (int i

我也学算法 - KMP算法

一直以来,对算法都是理论大于实际,甚至没有实际. 最近由于项目需要.从新了解了一下KMP算法.唉,讨厌这种被动的学习过程. 不过KMP算法还是很有意思的,用了两天的时间才总算是弄懂了.期间参考了网上的博文和数据结构.下面分享一下KMP算法的心得. KMP的总体思想是利用模式串本身的特性来优化匹配的步骤.如何利用自身的特性呢,KMP借助一个数组来实现,也就是大多数教程中提到的next数组.后面我会介绍next数组是如何构建和使用的. 前面提到KMP算法需要模式串满足一定的条件,那么这个条件是什么呢

算法 KMP算法 参考:http://blog.csdn.net/hackbuteer1/article/details/7319115

KMP算法详解: KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字.其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n). 在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀. 对于next[]数组的定义如下: 1) next[

关于的字符串的总结(群,子群,KMP算法,正则表达式):

字符串: 群: ? 群是一种只有一个运算的,简单的线性结构,可用来建立许多其他代数系统的一种基本结构. ? 设G是一个非空集合,a,b,c为它的任意元素.如果对G所定义的一种代数运算"."满足: 封闭性:a.b属于G 结合律:(ab)c=a(bc) 对于G中的任意元素a,b在G中存在唯一一个元素x,y,使得ax=b,ya=b,则称G对于所定义的运算构成一个群. 满足交换律是交换群 子群: ? 设H是群<G,.>的非空子集,则H是G的子群当且仅当H满足以下条件: 对任意的a,

KMP算法——从入门到懵逼到了解

本博文参考http://blog.csdn.net/v_july_v/article/details/7041827 关于其他字符串匹配算法见http://blog.csdn.net/WINCOL/article/details/4795369 暴力匹配算法 暴力匹配的思路,假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有: 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符: 如果失配(即S[i]! = P[j]),令i = i - (j

KMP算法深度解析

[原文参考] http://www.ics.uci.edu/~eppstein/161/960227.html 摘要:KMP算法是字符串匹配的经典算法,由于其O(m+n)的时间复杂度,至今仍被广泛应用.大道至简,KMP算法非常简洁,然而,其内部却蕴含着玄妙的理论,以至许多人知其然而不知其所以然.本文旨在解开KMP算法的内部玄妙所在,希望能够有助于学习与理解. 1.KMP算法    一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此称之为KMP算