C语言数据结构之模式匹配字符串定位问题

C语言数据结构之模式匹配字符串定位问题

什么是模式匹配字符串定位?

模式匹配字符串定位即在一个文本串中匹配一个模式串,并且返回模式串在文本串中第一次出现的位置。

例如,对于文本串“this is a test string”,我们想要匹配模式串“test”,我们期望得到的结果是第一次出现的位置为10。

KMP算法

算法思路

KMP算法是一种高效的字符串匹配算法。它的核心是利用已经匹配成功的信息,不断调整模式串的起始位置,从而达到减少匹配次数和提高匹配效率的目的。

具体地,我们用一个next数组来保存模式串每个字符在子串中出现时,如果失配该如何继续匹配的信息。并且我们从前缀和后缀比较的角度来得到每个字符在子串中的next值。

然后在匹配过程中,如果匹配失败了,我们利用next数组来更新模式串的起始位置。具体地,我们让模式串“跳过”已经匹配好的前缀,以达到快速匹配的目的。

代码示例

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define maxn 1000010
char p[maxn], t[maxn];
int next[maxn], lenp, lent;

void get_next() {
    int j = 0, k = -1;
    next[0] = -1;
    while (j < lenp) {
        if (k == -1 || p[j] == p[k]) {
            ++j;
            ++k;
            next[j] = k;
        } else {
            k = next[k];
        }
    }
}

int kmp() {
    int i = 0, j = 0;
    while (i < lent && j < lenp) {
        if (j == -1 || t[i] == p[j]) {
            ++i;
            ++j;
        } else {
            j = next[j];
        }
    }
    if (j == lenp) {
        return i - j;
    } else {
        return -1;
    }
}

int main() {
    scanf("%s %s", t, p);
    lenp = strlen(p);
    lent = strlen(t);
    get_next();
    printf("%d", kmp());
    return 0;
}

算法分析

KMP算法的时间复杂度是O(m+n),其中m和n分别是模式串和文本串的长度。

在实际应用中,通常m远小于n,因此KMP算法可以达到线性级别的时间复杂度,具有较高的效率。

BM算法

算法思路

BM算法是一种查找字符串的优秀算法,它的核心思想是利用规则来跳过尽可能多的匹配。具体地,BM算法分为两个阶段——预处理和匹配。

在预处理阶段,我们需要对模式串p进行预处理,以生成两个跳表,分别是“好后缀”跳表和“坏字符”跳表。

在匹配阶段,我们根据规则决定跳多少步,从而大幅度地减少匹配的次数。具体来说,我们先从右到左地扫描文本串t和模式串p,每当出现不匹配时,我们就利用好后缀和坏字符跳表来计算应该跳过的长度。然后将模式串的起始位置向右移动相应的步数,直到成功匹配模式串或者无法再移动为止。

代码示例

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define maxn 1000010
#define max(a, b) ((a)>(b)?(a):(b))

char p[maxn], t[maxn];
int lenp, lent, badchar[128], suffix[maxn], p_mxl[maxn];

void pre_badchar() {
    int l = strlen(p);
    for (int i = 0; i < l; i++) {
        badchar[p[i]] = i;
    }
}

void pre_suffix() {
    int l = strlen(p);
    suffix[l - 1] = l;
    int j = l - 1;
    for (int i = l - 2; i >= 0; i--) {
        if (j < i || suffix[l - j + i - 1] >= j - i) {
            if (j < i) {
                j = i;
            }
            while (j >= 0 && p[j] == p[l - 1 - i + j]) {
                --j;
            }
            suffix[i] = j - i;
        } else {
            suffix[i] = suffix[l - j + i - 1];
        }
    }
}

void pre_p_mxl() {
    int l = strlen(p);
    memset(p_mxl, 0, sizeof(p_mxl));
    for (int i = 0; i < l; i++) {
        int j = suffix[i];
        if (j == i + 1) {
            p_mxl[i] = j;
        } else {
            p_mxl[i] = max(p_mxl[i + 1] - 1, j);
        }
    }
}

int bm() {
    int i = 0, j;
    while (i <= lent - lenp) {
        for (j = lenp - 1; j >= 0 && p[j] == t[i + j]; --j);
        if (j < 0) {
            return i;
        } else {
            i += max(p_mxl[j], j - badchar[t[i + j]]);
        }
    }
    return -1;
}

int main() {
    scanf("%s %s", t, p);
    lenp = strlen(p);
    lent = strlen(t);
    pre_badchar();
    pre_suffix();
    pre_p_mxl();
    printf("%d", bm());
    return 0;
}

算法分析

BM算法是一种高效的字符串匹配算法。一般情况下,BM算法的效率比KMP算法高。

在实际应用中,BM算法的最坏时间复杂度是O(mn),但在大多数情况下,BM算法能够获得O(m/n)的时间复杂度。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构之模式匹配字符串定位问题 - Python技术站

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

相关文章

  • Java实题演练二叉搜索树与双向链表分析

    Java实题演练二叉搜索树与双向链表分析 题目描述 给定一个二叉搜索树,将它转换成一个排序的双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。 思路分析 对于一颗二叉搜索树,有以下性质: 若左子树不为空,则左子树上所有结点的值均小于它的根结点的值; 若右子树不为空,则右子树上所有结点的值均大于它的根结点的值; 左右子树也为二叉搜索树。 我们考虑…

    数据结构 2023年5月17日
    00
  • C语言学习之链表的实现详解

    下面我将详细讲解“C语言学习之链表的实现详解”的完整攻略。 1. 链表的定义 链表是一种数据结构,它由一系列节点组成。每个节点由一个数据部分和一个指向下一个节点的地址部分组成。链表可以有多种形式,例如单向链表、双向链表、循环链表等。 2. 链表的实现 2.1. 单向链表 单向链表是最简单的链表形式,一个节点只包含一个指向下一个节点的指针。在C语言中,我们可以…

    数据结构 2023年5月17日
    00
  • C语言数据结构深入探索顺序表

    C语言数据结构深入探索顺序表攻略 一、概述 顺序表是一种线性结构,是计算机程序中最常见的数据结构之一。在C语言中,顺序表可以用数组来实现。本篇文章将深入讲解顺序表的原理和实现方法,帮助读者加深对顺序表的理解,并掌握如何用C语言代码实现顺序表。 二、顺序表的定义和特点 顺序表是指用一组地址连续的存储单元依次存储线性表中的各个元素,用于表示具有相同数据类型的n个…

    数据结构 2023年5月17日
    00
  • 数据结构与算法大作业:走迷宫程序(C语言,DFS)(代码以及思路)

    好家伙,写大作业,本篇为代码的思路讲解   1.大作业要求 走迷宫程序 问题描述: 以一个 m * n 的长方阵表示迷宫, 0和1分别表示迷宫的通路和障碍。 设计一个程序, 对任意设定的迷宫, 求出一条从入口到出口的通路, 或得出没有通路的结论。 基本要求: (1) 实现一个以链表做存储的栈类型, 然后编写一个求解迷宫的非递归程序。 求的通路以三元组(i, …

    算法与数据结构 2023年5月9日
    00
  • 数据结构TypeScript之二叉查找树实现详解

    数据结构TypeScript之二叉查找树实现详解 什么是二叉查找树 二叉查找树(Binary Search Tree,简称BST)是一种基础的数据结构,也是一种常用的搜索算法。它通过以二叉树的形式表示各个结点之间的关系,实现了快速查找、添加、删除等操作。对于任何一个节点,其左子树上的节点值均小于该节点的值,右子树上的节点值均大于该节点的值。 二叉查找树的实现…

    数据结构 2023年5月17日
    00
  • 数据结构 – 绪论

    01.绪论 1. 概念 1.1 数据结构 数据 Data:信息的载体。能被计算机识别并处理的符号的集合。 数据元素 Data element:数据的基本单位,通常作为一个整体进行考虑和处理。一个数据元素往往由若干数据项组成。数据项是组成数据元素的不可分割的最小单位。 如学生的信息记录就是一个数据元素,它由学号、姓名、性别等组成。 数据对象 Data obje…

    算法与数据结构 2023年4月18日
    00
  • oracle 数据库学习 基本结构介绍

    Oracle 数据库学习:基本结构介绍攻略 概述 Oracle 数据库是目前世界上使用最为广泛的一种关系型数据库。学习 Oracle 数据库需要具备一定的数据库基础知识,特别是SQL语言的使用,才能更好地理解 Oracle 数据库的基本结构。本攻略将从以下几个方面介绍 Oracle 数据库的基本结构: 数据库系统组成; Oracle 实例; 数据库; 表空间…

    数据结构 2023年5月17日
    00
  • Java实现链表数据结构的方法

    Java实现链表数据结构的方法可以分为以下步骤: 定义链表节点类Node 首先,在Java中实现链表数据结构,需要定义一个链表节点类,称为Node。Node类中包含两个重要属性: 数据域data,用于存储每个节点的数据信息。 指针域next,用于存储下一个节点的引用。 代码示例: public class Node { public int data; //…

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