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日

相关文章

  • Python实现的数据结构与算法之基本搜索详解

    Python实现的数据结构与算法之基本搜索详解 在计算机科学中,搜索指的是在一组数据中找到目标数据的过程。搜索算法是解决各种问题的关键,即使是拼图游戏和图像识别也要依赖搜索算法。本文将介绍基本的搜索算法,包括线性/顺序搜索、二分搜索和广度优先搜索。 线性/顺序搜索 顺序搜索又称为线性搜索,它遍历整个数据集以查找特定元素。顺序搜索可以用于查找未排序的列表。该算…

    数据结构 2023年5月17日
    00
  • C语言程序设计第五版谭浩强课后答案(第二章答案)

    首先,需要说明的是本题涉及到一个特定的知识领域,即C语言程序设计,以及该领域内某个具体教材的课后习题解答。因此,本攻略的重心将放在如何利用Markdown格式对该领域内的知识进行准确、清晰的表达和展示上。 下面是本攻略的目录: C语言程序设计第五版谭浩强课后答案(第二章答案)攻略 一、简介 二、题目列表 三、示例说明 示例一 示例二 四、总结 一、简介 本攻…

    数据结构 2023年5月17日
    00
  • 数据结构串的操作实例详解

    数据结构串的操作实例详解 什么是数据结构串? 数据结构串是由若干个字符按照一定的顺序排列而成的线性结构。可以对串进行许多操作,如子串的截取、串的连接、串的替换等等。 数据结构串的基本操作 串的初始化 为了操作一个串,我们需要先定义一个串并初始化,可以通过以下代码实现: #include <stdio.h> #define MAXSIZE 100 …

    数据结构 2023年5月17日
    00
  • 手写 Vue3 响应式系统(核心就一个数据结构)

    下面是手写 Vue3 响应式系统的完整攻略。 1. 概述 Vue3 的响应式系统使用了 Proxy 对象来监测对象的变化,相较于 Vue2 的响应式系统使用 Object.defineProperty 进行数据劫持,Proxy 具有更好的性能和更简洁的 API。 当我们修改 Vue3 中的 reactive 对象内部的数据时,就会触发依赖收集和派发更新的操作…

    数据结构 2023年5月17日
    00
  • C语言数据结构旋转链表的实现

    C语言数据结构旋转链表的实现 1. 什么是旋转链表 旋转链表是一种特殊的链表,其特点是将链表的最后一个节点移动到最前面,形成一个环形链表的效果。比如下面这个链表: 1 -> 2 -> 3 -> 4 -> 5 经过一次旋转之后变成了: 5 -> 1 -> 2 -> 3 -> 4 2. 实现思路 旋转链表的实现思路…

    数据结构 2023年5月17日
    00
  • C++数据结构之AVL树的实现

    C++数据结构之AVL树的实现 什么是AVL树 AVL树是一种自平衡二叉查找树,也就是说它通过旋转操作来保持树的平衡。 在AVL树中,任何节点的两个子树高度差不超过1。如果高度差大于1,则需要通过旋转操作来调整树的平衡。 AVL树提供了比红黑树更快的插入和删除操作,但是在读取数据时红黑树更快。 AVL树的实现 结构体定义 我们可以先定义一个结构体来表示AVL…

    数据结构 2023年5月17日
    00
  • ecnuoj 5042 龟速飞行棋

    5042. 龟速飞行棋 题目链接:5042. 龟速飞行棋 赛中没过,赛后补题时由于题解有些抽象,自己写个题解。 可以发现每次转移的结果只跟后面两个点的胜负状态有关。 不妨设 \(f_{u,a,b}\) 表示,\(u+1\) 号点的胜负态为 \(a\),\(u+2\) 号点的胜负态为 \(b\),此时从 \(1\) 号点出发的胜负态是什么。那么可以发现,利用 …

    算法与数据结构 2023年4月17日
    00
  • java数据结构基础:算法

    Java数据结构基础:算法攻略 概述 在程序员的日常开发中,算法是一项重要的技能,而数据结构则是算法不可缺少的基础。本文将讲解Java数据结构中的基本算法,包括常见算法的实现,算法的分析及算法的运用。经过本文的学习,读者可以掌握Java中基础的算法实现及应用。 常见算法实现 排序算法 排序算法是算法中最基础的一类,常用的算法有冒泡排序、插入排序、选择排序、快…

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