数据结构升华部分:排序与字符串匹配算法应用

news2024/9/28 15:32:25

数据结构入门学习(全是干货)——综合应用

习题选讲 - 排序与字符串匹配算法

习题选讲 - Insert or Merge

习题-IOM.1 插入排序的判断

题意理解

如何区分简单插入和非递归的归并排序

  1. 插入排序:前面有序,后面没有变化。
  2. 归并排序:分段有序。

捏软柿子算法

  • 在插入和归并两种算法里,判断插入排序较容易。

判断是否为插入排序

  1. 从左向右扫描,直到发现顺序不对,跳出循环。
  2. 从跳出地点继续向右扫描,与原始序列比对,若发现不同,则判断为“非插入排序”。如果在对比过程中发现不同,跳出循环。
  3. 循环自然结束,则判断为“是”,返回跳出地点。

解析:可以返回一个布尔值,例如非为0、是为1,但如果返回“是”,插入排序需继续进行,从左向右扫描找到执行下一步的地点。因此返回“是”的同时返回跳出地点。

如果是插入排序,则从跳出地点开始进行一趟插入。

习题-IOM.2 归并段的判断

判断归并段的长度

错误的想法:

  1. 从头开始连续有序的子列长度?
  2. 所有连续有序子列的最短长度?
  • 保险的判断方法:从原始序列出发,真正进行归并排序。每归并一趟就将归并的中间结果与当前序列做比对,什么时候每一个数都对上了就继续执行。
for (l=2;l<=N;l*=2)
    //在保证了l是4的情况下,要检查看能不能是8,我们要重复前面的步骤看两段之间的衔接点是不是有序

  • 红色位置没有序了时跳出循环,此时l为4,直接以4为归并段继续执行下一趟的归并。

其他数据测试

最小N(应该多大?)

边界测试是每道题的关键组成部分。

  • N等于1时,序列仅一个数字,排序前后结果相同,因此解不唯一。要求区分两种算法的最小N为4:
    1. 插入排序第一步,无变化。
    2. 归并排序第一步,所有元素变了。

最大N

习题选讲 - Sort with Swap(0,*)

习题-SWS.1 环的分类

题意理解

  • 给定N个数字的排列,如何仅利用与0交换达到排序目的?0扮演空位的角色。

环的分类

习题-SWS.2 算法示例

对于不包含0的交换操作次数为n+1,包含0则是n-1次。

习题选讲 - Hashing - Hard Version

习题-HHV 算法思路概述

这是哈希问题的逆问题

题意理解

  1. 已知H(x) = x%N,利用线性探测解决冲突问题。
  2. 先给出散列映射的结果,反求输入顺序。
    • 当元素x被映射到H(x)位置,发现该位置已被y占用,则y一定在x之前被输入。

限制:为确保解唯一,若几个元素可能同时被插入,则按从小到大顺序插入。

因为12模11,余数为1,所以跟12冲突,放在12下面。后面都是类型的操作

依次输入顺序为

串的模式匹配(KMP算法)

KMP-1. 问题及简单解决方案

什么是串

  1. 线性存储的一组数据(默认是字符)。

  2. 特殊操作集。

    1.求串的长度
    2.比较两串是否相等
    3.两串相接
    4.求子串
    5.插入子串
    6.匹配子串(有难度)
    7.删除子串
    

什么是串的模式匹配

目标:给定一段文本,从中找出某个指定的关键字

例如从一本Thomas Love Peacock写于十九世纪的小说《Headlong Hall》中找到那个最长的单词: osseocarnisanguineoviscericartilaginonervomedullary

或者从古希腊喜剧《Assemblywomen》中找到一道菜的名字: Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon

模式匹配目标

  • 给定文本,从中找出指定的关键字。

Position PatterMatch(char *string,char *pattern)//position指位置
    //模式匹配就是给定一段文本(string),给定一个模式(*pattern),我们要通过PatterMatch函数来返回这个pattern里string第一次出现的位置

简单实现

方法1:C语言库函数strstr。

接口:char *strstr(char *string,char *pattern)
    //返回的是char *这个类型的变量(指向某个字符的指针),变量里面存的是pattern这个字符串第一个字母在string出现的时候那个字母所在的位置
    //一个小Demo
#include <stdio.h>
#include <string.h>//库要记得包含进来
    
typedef char* Position;//给char*重新起个名字,让不懂的人也可以知道返回的是一个位置

int main()
{
    char string[] = "This is a simple example.";
    char pattern[] = "simple";
    Position p = strstr(string,pattern);
    if( p == NotFound ) printf("Mot Found.\n");//能不能找到进行一个判断
    else printf("%s\n",p);
    return 0;
}
//输出:simple example.
//如果输入的找不到,就会输出一个空指针(#define NotFound NULL)

  • strstr的最坏时间复杂度为O(nm),当模式较小时可用,但当两者都较大时需谨慎。

简单改进

方法2:从末尾开始比。

时间复杂度:T = O(n)//仅仅是根据上方的例子进行的改动,如果pattern = "aab"换成"baa"一样要芭比Q
    所以这个改进是没啥作用的
KMP-2. KMP 算法思路

大师改进

方法3:KMP算法,时间复杂度为O(n+m)。

  • 简单的往前错一位的比较是完全没有必要的没有意义的,如下图

  • KMP算法的想法:

  • 指针x不回退,继续从x开始比较。

match的具体例子

下标从090个字符对应的是一个长度为1的子串,所以他不可能产生匹配,match就永远是-101:a跟b是配不上的,match也为-1
0-2:a和c配不上,ab和bc也配不上,所以match还是为-1
0-3:ab和ca是配不上的,abc跟bca也配不上,a对应的j为0,所以match也为0
//此时限制条件是最大i是小于j的,如果i=j的话那就相当于自己等于自己就没有意义了(p0...pj = p0...pj)
    //所以我们考虑他的真子串
0-4:a跟b配不上,abc跟cab配不上,ab跟ab能配上,match值为1...
  • 对于pattern = abcabcacab,最后3个字符的match值为-1, 0, 1。

对于 pattern = abcabcacab,最后 3 个字符的 match 值是多少?-1, 0, 1

在早期的教科书上被叫做failure(失败的意思)

match值的含义:

例子:从0到6的子串,首跟尾能配上的小串,从0开始他的尾部下标为3,abca跟abca能配上。这就是match的含义

此代码块内容来自百度百科:
    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)
    
    KMP算法是三位学者在 Brute-Force算法的基础上同时提出的模式匹配的改进算法。Brute- Force算法在模式串中有多个字符和主串中的若干个连续字符比较都相等,但最后一个字符比较不相等时,主串的比较位置需要回退。KMP算法在上述情况下,主串位置不需要回退,从而可以大大提高效率

模式匹配类型

(1)精确匹配
如果在目标T中至少一处存在模式P,则称匹配成功,否则即使目标与模式只有一个字符不同也不能称为匹配成功,即匹配失败。给定一个字符或符号组成的字符串目标对象T和一个字符串模式P,模式匹配的目的是在目标T中搜索与模式P完全相同的子串,返回T和P匹配的第一个字符串的首字母位置  。
(2)近似匹配
如果模式P与目标T(或其子串)存在某种程度的相似,则认为匹配成功。常用的衡量字符串相似度的方法是根据一个串转换成另一个串所需的基本操作数目来确定。基本操作由字符串的插入、删除和替换来组成
KMP-3. KMP 算法实现
    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)
    
    KMP算法是三位学者在 Brute-Force算法的基础上同时提出的模式匹配的改进算法。Brute- Force算法在模式串中有多个字符和主串中的若干个连续字符比较都相等,但最后一个字符比较不相等时,主串的比较位置需要回退。KMP算法在上述情况下,主串位置不需要回退,从而可以大大提高效率
  • KMP算法实现示意。

一直走到指针不匹配

Position KMP(char *string,char *pattern )
{
    int n = strlen(string);//strlen得到string的长度,下方也是一样 复杂度:O(n)
    int m = strlen(pattern);//复杂度:O(m)
    int s,p,*match;//声明两个指针
    if(n < m) return NotFound;//找的n不可能比m短 
    match = (int *)malloc(sizeof(int) *m);
    BuildMatch(pattern,match);//Tm = O(?)
    s = p =0;
    while( s<n &&p<m){  //当这两个指针一起往前飞,任何一个指针先指到自己指的串的末尾的时候结束,复杂度O(n)
    	if(string[s] == pattern[p]){ s++;p++; }//p有时候加加有时候回退,但s永远加加
    	else if (p>0) p = match[p-1]+1;//为了防止得到段错误,这里加上条件p>0
    //如果p = 0的话,意味着pattern从第一个字符就不匹配,这个时候p不动,s向前走一格
    	else s++;//当string[s] == pattern[p]不匹配,我们s++,继续下一轮匹配
	}
    //在我们跳出while循环的时候,p指针已经碰到pattern的末尾(p==m),那就是完全的匹配上了
    //反之p还没有到结尾,而string已经到p的结尾了,就意味着我们找不到这个模式
    return (p == m) ? (s-m) : NotFound; 
}

KMP的整体时间复杂度
  • T = O(n+m+Tm)。
KMP-4. BuildMatch 的实现原理

  • 如果采用这种方法,时间复杂度将达到Tm = O(m³)。

新想法:计算j的match值与j-1的match值的关系。

假如我们这是从0到j-1的字段

  • match[j] = match[j-1] + 1(最多持平)。

如果 match[j-1]+1 这个位置上的字符与 j 位置上的字符相等,match[j] 会有可能比 match[j-1]+1 更大吗?没可能

match[j] = match[j-1] + 1 (最多持平啦,利用反证法证明)

且能得到这个结果的前提是运行很好

当 pattern[match[j-1]+1] != pattern[j] 时,下一个待与 pattern[j] 比较的元素下标是:match[match[j-1]]+1

KMP-5. BuildMatch的编程实现
void BuildMatch(char *pattern, int *match) {
    int i, j;
    int m = strlen(pattern); // 复杂度O(m)
    match[0] = -1; // 初始化
    for (j = 1; j < m; j++) { // 复杂度O(m)
        i = match[j - 1]; // 获取前一个match值
        while ((i >= 0) && (pattern[i + 1] != pattern[j])) // 检查条件
            i = match[i]; // 回退
        if (pattern[i + 1] == pattern[j])
            match[j] = i + 1; // 更新match值
        else
            match[j] = -1; // 无匹配
    }
}

整个算法复杂度:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2168538.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JUC高并发编程3:线程间通信

1 线程间通信 线程间通信的模型有两种&#xff1a;共享内存和消息传递&#xff0c;以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析 场景&#xff1a;两个线程&#xff0c;一个线程对当前数值加 1&#xff0c;另一个线程对当前数值减 1,要求用线程间…

【智能控制】第15章 智能优化算法,遗传算法

目录 15.1 遗传算法及其应用 15.1.1 遗传算法的基本原理 15.1.2 遗传算法的特点 15.1.3 遗传算法的应用领域 遗传算法的应用 15.1.4 遗传算法的设计 遗传算法的应用步骤 15.1.5 遗传算法求函数极大值 随着优化理论的发展&#xff0c;一些新的智能算法得到了迅速发…

深度学习:ResNet残差神经网络

目录 一、什么是ResNet残差神经网络 二、残差结构 三、18层残差网络 1.最初残差网络变体 2.图片示例 3.表格示例 四、批次归一化&#xff08;Batch Normalization&#xff09; 1.工作过程 2.主要作用 五、ResNet残差神经网络解决了传统神经网络什么问题 1.梯度消失和…

node-red-L3-重启指定端口的 node-red

重启指定端口 目的步骤查找正在运行的Node.js服务的进程ID&#xff08;PID&#xff09;&#xff1a;停止Node.js服务&#xff1a;启动Node.js服务&#xff1a; 目的 重启指定端口的 node-red 步骤 在Linux系统中&#xff0c;如果你想要重启一个正在运行的Node.js服务&#x…

【AI绘画】Midjourney进阶:光影控制详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;为什么要学习光影控制光影控制的作用 &#x1f4af;强化主题hard lighting&#xff08;硬光 &#xff09;soft lighting&#xff08;软光/柔光&#xff09;测试 &…

利用Puppeteer-Har记录与分析网页抓取中的性能数据

引言 在现代网页抓取中&#xff0c;性能数据的记录与分析是优化抓取效率和质量的重要环节。本文将介绍如何利用Puppeteer-Har工具记录与分析网页抓取中的性能数据&#xff0c;并通过实例展示如何实现这一过程。 Puppeteer-Har简介 Puppeteer是一个Node.js库&#xff0c;提供…

Leetcode面试经典150题-322.零钱兑换

给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。 你可以认为每种硬币的数量是无限的。 示…

[数据库实验一]数据库和表

目录 一、实验目的与要求 二、实验内容 实验小结 一、实验目的与要求 1.掌握MySQL中如何创建数据库和表的方法 2.熟练掌握MySQL的数据类型、主键实体完整性的设置 3.参照完整性的定义及应用 4.插入数据 5.数据库的备份操作 二、实验内容 &#xff11;、创建名为fruit…

CleanMyMac X 评价、介绍、使用教学|Mac系统最推荐的系统优化和清理软件工具!

本篇文章要带大家看一款知名的Mac系统优化、清理工具– CleanMyMac X &#xff0c;并且也会附上详细的介绍和使用教学。 链接: https://pan.baidu.com/s/1_TFnrIVH1NGsZPsA3lpwAA 提取码: dpjw CleanMyMac X-安装包&#xff1a;https://souurl.cn/QUYb57 为什么Mac电脑需要装系…

Cilium + ebpf 系列文章-什么是ebpf?(一)

前言&#xff1a; 这篇非常非常干&#xff0c;很有可能读不懂。 这里非常非常推荐&#xff0c;建议使用Cilium官网的lab来辅助学习&#xff01;&#xff01;&#xff01;Resources Library - IsovalentExplore Isovalents Resource Library, your one-stop destination for ins…

FocSAM

Dynamic Window简写为Dwin 辅助信息 不建议复现

TCN-Transformer+GRU多变量时间序列预测(Matlab)

超强来袭&#xff01;双路创新&#xff01;TCN-TransformerGRU多变量时间序列预测&#xff08;Matlab&#xff09; 目录 超强来袭&#xff01;双路创新&#xff01;TCN-TransformerGRU多变量时间序列预测&#xff08;Matlab&#xff09;效果一览基本介绍程序设计参考资料 效果一…

智慧农业的引擎:高标准农田灌区信息化的探索与实践

在现代农业的广阔图景中&#xff0c;智慧农业作为一股革新力量&#xff0c;正逐步重塑着传统农业的面貌。其中&#xff0c;高标准农田灌区的信息化建设不仅是智慧农业的重要引擎&#xff0c;更是实现农业可持续发展、提高资源利用效率的关键路径。 高标准农田灌区信息化的内涵…

Linux下的基本指令/命令(二)

热键 Tab&#xff1a; 连点两次 对命令进补齐 或者 显式 以目前所需字母 开头的指令。 也可以进行路径补齐 或者 显示所写的文件所处路径上的所有文件。 如果什么也没写&#xff0c;直接按Tab会显示所有命令 Ctrl C&#xff1a; 一旦出现失控的状态&#xff0c;或者任何无法…

刷题计划 day10 栈与队列上【用栈实现队列】【用队列实现栈】【有效的括号】【删除字符串中的所有相邻重复项】

⚡刷题计划day10栈与队列继续&#xff0c;可以点个免费的赞哦~ 往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的支持是我的最大动力&#x1f339;~ 目录 ⚡刷题计划day10继续&#xff0c;可以点个免费的赞哦~ 往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的…

Linux云计算 |【第四阶段】NOSQL-DAY2

主要内容&#xff1a; Redis集群概述、部署Redis集群&#xff08;配置manage管理集群主机、创建集群、访问集群、添加节点、移除节点&#xff09; 一、Redis集群概述 1、集群概述 所谓集群&#xff0c;就是通过添加服务器的数量&#xff0c;提供相同的服务&#xff0c;从而让…

CSDN文章导出md并迁移至博客园

一、获取所有文章地址 1.进csdn首页&#xff0c;点击自己的头像 2.在个人主页界面&#xff0c;按F12打开控制台&#xff0c;并找到network&#xff0c;找到get-business开头的请求&#xff0c;右键copy他的url 3.选择console,输入一下代码&#xff0c;其中fetch里面的url是你刚…

62.【C语言】浮点数的存储

目录 1.浮点数的类型 2.浮点数表示的范围 3.浮点数的特性 《计算机科学导论》的叙述 4.浮点数在内存中的存储 答案速查 分析 前置知识:浮点数的存储规则 推导单精度浮点数5.5在内存中的存储 验证 浮点数取出的分析 1.一般情况:E不全为0或不全为1 2.特殊情况:E全为0…

P335_0334韩顺平Java_零钱通介绍

目录 P335_0334韩顺平Java_零钱通介绍代码过程编程OOP&#xff08;Object-Oriented Project&#xff09; 参考资料 P335_0334韩顺平Java_零钱通介绍 先完成显示菜单&#xff0c;并可以选择。完成零钱通明细。完成收益入账。消费。退出。 PS&#xff1a;判断时尽量用不正确的条…

BEV学习---LSS4-模型训练

主要借鉴如下链接&#xff1a; https://blog.csdn.net/m0_51579041/article/details/140746160 测试命令如下&#xff0c;均已跑通&#xff1a; # 验证集iou计算&#xff1a; python main.py eval_model_iou mini -bsz1 --nworkers0 --gpuid0 --modelf./model/model525000.pt…