浅谈Python描述数据结构之KMP篇

浅谈Python描述数据结构之KMP篇

简介

本篇文章将着重介绍KMP算法,其中包含KMP算法的基本原理、实现步骤以及Python代码实现示例。KMP算法是一种高效的字符串匹配算法,它可以在O(m+n)的时间内完成字符串的匹配操作,其中m和n分别为主串和模式串的长度。

基本原理

KMP算法(Knuth-Morris-Pratt算法)是一种字符串匹配算法,它的基本思想是通过“部分匹配表”来避免不必要的比较操作。具体来说,它在匹配过程中,当某个字符匹配失败时,不是直接跳转到下一个字符进行比较,而是根据已匹配的结果来确定下一个比较的位置。这个过程中,部分匹配表就发挥了重要作用,它能够提供已匹配的信息,以及在匹配失败时的跳转位置。

实现步骤

KMP算法的实现步骤主要包括以下几个部分:

  1. 构建部分匹配表
  2. 在主串和模式串中进行匹配
  3. 根据部分匹配表调整匹配位置

其中,构建部分匹配表是整个算法中最重要的一步,需要单独解释。

构建部分匹配表

部分匹配表是模式串本身的一个数组,用来储存模式串的每个位置上,从头开始的子串的最长公共前后缀长度。具体地,设模式串为p,p的长度为m,则部分匹配表的长度也为m。在第i个位置上,部分匹配表的值表示p[:i+1]这个子串的最长公共前后缀长度。需要注意的是,这里的公共前后缀必须是非自身重复的,否则会出现算法错误。以p="ABCDABD"为例,它的部分匹配表为:

字符串 A B C D A B D
部分匹配表 0 0 0 0 1 2 0

在主串和模式串中进行匹配

在进行匹配时,我们将主串和模式串对齐,从左到右逐个比较,步骤如下:

  1. 如果当前字符匹配成功,即S[i]==P[j],则i++,j++
  2. 如果当前字符匹配失败,则根据部分匹配表j的值来调整j的位置。具体地,设当前子串为S[i-k:i],部分匹配表为next[],则j=next[k]。
  3. 如果j=-1,则表示主串的当前位置i无法与模式串中任何位置匹配,此时i++,j++

需要注意的是,对于模式串的第一个字符,我们是不做比较,而是从第二个字符开始匹配。

根据部分匹配表调整匹配位置

在匹配失败时,我们需要根据部分匹配表来调整j的位置,具体地,设当前子串为S[i-k:i],部分匹配表为next[],则j=next[k]。需要注意的是,如果next[k]大于0,则部分匹配表的值本身就蕴含了“跳跃”的信息,即主串中不必从i-k这个位置开始逐个比较,而是可以直接跳到j=next[k]这个位置,从下一个字符开始比较。

Python代码实现示例

下面是一个简单的Python实现示例:

def kmp_search(s, p):
    """
    KMP算法,用于字符串匹配
    """
    m, n = len(s), len(p)
    next = get_next(p)
    i, j = 0, 0
    while i<m and j<n:
        if j==-1 or s[i]==p[j]:
            i += 1
            j += 1
        else:
            j = next[j]
    if j == n:
        return i - j
    return -1

def get_next(p):
    """
    构建部分匹配表
    """
    n = len(p)
    next = [-1] * n
    i, j = 0, -1
    while i<n-1:
        if j==-1 or p[i]==p[j]:
            i += 1
            j += 1
            next[i] = j
        else:
            j = next[j]
    return next

下面是一个简单的例子,演示了如何在主串s中查找模式串p。

s = "BBC ABCDAB ABCDABCDABDE"
p = "ABCDABD"
pos = kmp_search(s, p)
if pos == -1:
    print("Pattern not found in string.")
else:
    print(f"Pattern found at position {pos}.")

示例说明

上述示例中,我们依次完成了以下操作:

  1. 首先定义了一个主函数kmp_search和一个辅助函数get_next。
  2. 在kmp_search函数中,我们首先使用get_next函数来生成部分匹配表,然后设置i,j的初值为0。
  3. 在while循环的过程中,我们依次比较s[i]和p[j],如果匹配成功,则继续下一组比较;如果匹配失败,则根据部分匹配表重新设置j的位置。
  4. 最后,如果j等于n,说明p已经完整匹配成功,返回i-j作为匹配位置;否则,返回-1表示匹配失败。
  5. 在最后一个代码块中,我们定义了一个主串s和一个模式串p,然后使用kmp_search函数来查找p在s中出现的位置,并将结果打印输出。

结论

KMP算法是一种高效的字符串匹配算法,相比于朴素的字符串匹配算法,它能够避免无谓的比较操作,减少了算法的时间复杂度。在实际应用中,KMP算法具有较为广泛的使用场景,如文本匹配、模式识别、音频处理等。掌握KMP算法的原理和实现方法,对于提高程序的效率和准确性具有非常重要的意义。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Python描述数据结构之KMP篇 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Java深入了解数据结构之栈与队列的详解

    Java深入了解数据结构之栈与队列的详解 1. 栈的概念 栈(Stack)是一种先进后出的数据结构,类似于一个箱子,新的物品只能放到箱子的顶部,旧的物品只能从箱子的顶部取出。栈通常有下面几个基本操作: push:将元素压入栈中,放在栈顶。 pop:将栈顶元素弹出,如果栈为空,则抛出异常。 peek:返回栈顶元素,但不将其弹出,如果栈为空,则抛出异常。 isE…

    数据结构 2023年5月17日
    00
  • C++数据结构之哈希算法详解

    C++数据结构之哈希算法详解 概述 哈希算法是一种常用于对数据进行快速检索的算法,它通常将数据映射为一个较短的指纹码,并将这个指纹码作为数据的索引值,这样可以快速地根据索引值找到对应的数据。 本文将详细讲解哈希算法的实现原理、常见应用场景以及在 C++ 语言中如何实现一个简单的哈希表。 哈希算法的实现原理 哈希算法的核心思想是将输入数据通过一个哈希函数进行映…

    数据结构 2023年5月17日
    00
  • 【ACM组合数学 | 错排公式】写信

    题目链接:https://ac.nowcoder.com/acm/contest/54484/B 题意很简单,但是数据范围偏大。 错排公式 首先来推导一下错排公式: \[D(n) = n!\sum_{k=0}^{n}\frac{(-1)^k}{k!} \] 设一个函数: \[S_i表示一个排列中p_i = i的方案数 \] 那么我们可以知道: \[D(n) …

    算法与数据结构 2023年4月17日
    00
  • C语言数据结构之队列算法详解

    C语言数据结构之队列算法详解 什么是队列? 在计算机科学中,队列是一种抽象数据类型或线性数据结构。它具有先进先出(FIFO)的特性,即先进入队列的元素先被处理或先被移除。队列通常用于解决先到先服务的问题(如请求处理),但也常用于广泛的异步编程中。 队列的特点 队列通常具有以下特点: 队列可以为空; 队列从队首插入元素,从队尾移除元素; 队列只允许从队尾插入元…

    数据结构 2023年5月17日
    00
  • C语言中数据结构之链式基数排序

    C语言中数据结构之链式基数排序 概述 链式基数排序是基数排序的一种实现方式。基数排序是一种桶排序算法,它通过将需要排序的数据分成多个桶,并且按照一定的顺序将数据从桶中取出来,以达到排序的目的。链式基数排序则使用了链表结构来实现桶的功能。 实现步骤 链式基数排序的实现步骤如下: 申请链表节点数组,并初始化链表头结点数组。链表的数量等于指定的基数,例如10进制的…

    数据结构 2023年5月17日
    00
  • C语言数据结构之栈简单操作

    C语言数据结构之栈简单操作 什么是栈? 栈(Stack)是一种线性数据结构,它具有“后进先出”(Last-In-First-Out)的特性。栈顶是栈的一端,另一端称为栈底。每次只能从栈顶插入数据(入栈)或者从栈顶取出数据(出栈)。 栈的简单操作 栈的简单操作包括: 初始化栈 判断栈是否为空 判断栈是否已满 入栈操作 出栈操作 获取栈顶元素 栈的初始化 栈的初…

    数据结构 2023年5月16日
    00
  • 如何配置git环境

    首先我们新建一个文件夹;    然后我们右键git Bash Here一下;在里面输入: cd ssh-keygen cd.ssh ls (注意,我们要是之前就生成过密钥,直接输入ls就好了) 输入ls之后,会显示出来我们的公钥,我们输入: cat id_rsa.pub 然后密钥就出来了,密钥出来之后,我们把密钥复制一下,打开github 选择设置; 中会有…

    算法与数据结构 2023年4月18日
    00
  • 带你了解Java数据结构和算法之2-3-4树

    带你了解Java数据结构和算法之2-3-4树 1. 什么是2-3-4树 2-3-4树是一种自平衡二叉查找树,也叫B树的一种,它可以保持树的平衡,使得每个节点的左右子树高度差最多为1。在2-3-4树中,每个节点可以包含2个、3个或4个子节点,这也是其名称的来源。2-3-4树是B树的特殊形式,通常用于内存储存结构。 2. 2-3-4树的特点 2-3-4树的特点如…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部