算法设计与分析实验报告python实现(串匹配问题、采用分治法求解最大连续子序列和问题、用分治策略求众数问题、最近点对问题)

一、 实验目的

1.加深学生对算法设计方法的基本思想、基本步骤、基本方法的理解与掌握;
2.提高学生利用课堂所学知识解决实际问题的能力;
3.提高学生综合应用所学知识解决实际问题的能力。

二、实验任务

1、串匹配问题
给定一段文本,在该文本中查找并定位任意给定字符串。
要求:
(1)实现BF算法;
(2) 实现BF算法的改进算法:KMP算法
2、采用分治法求解最大连续子序列和问题
给定一个有n(n≥1)个整数的序列,要求求出其中最大连续子序列的和。
例如: 序列(-2,11,-4,13,-5,-2)的最大子序列和为20序列(-6,2,4,-7,5,3,2,-1,6,-9,10,-2)的最大子序列和为16。
3、用分治策略求众数问题
问题描述:给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数。多重集S中重数最大的元素称为众数。要求对给定的又n个自然数的组成的多重集S,计算S的众数及其重数。
4、最近点对问题
设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。
(1)分别用蛮力法和分治法求解最近对问题;
(2)分析算法的时间性能,设计实验程序验证分析结论。

三、实验设备及编程开发工具

实验设备:Win10电脑
开发工具:Python 3.7,Pycharm

四、实验过程设计(算法思路及描述,代码设计)

1、串匹配问题

给定一段文本,在该文本中查找并定位任意给定字符串。
要求:
(1)实现BF算法;
(2)实现BF算法的改进算法:KMP算法

(1)解题思路:
BF算法就是暴力求解,用所求字符串s2与主串s1做匹配,当不匹配时,从本次主串循环的下一个字符开始重新匹配。

代码:

def BF_algorithm(s1,s2): 
    n1 = len(s1) 
    n2 = len(s2)
    i,j = 0,0
    while i < n1 and j < n2:
        if (s1[i] == s2[j]):
            i += 1
            j += 1
        else:
            i = i - j + 1
            j = 0
    if j >= n2:
        return i - n2
    else:
        return -1

(2)解题思路:

KMP算法需要一个next数组,next数组的含义就是一个固定字符串的最长前缀和最长后缀相同的长度。当匹配失败时,数组下标会移动到最长前缀的后一个位置,从而减少了重复匹配。

代码:

def get_next(p):
    i, k, m = 0, -1, len(p)
    p_next = [-1] * m
    while i < m-1:
        if k == -1 or p[i] == p[k]:
            i, k = i+1, k+1
            if p[i] == p[k]:
                p_next[i] = p_next[k]
            else:
                p_next[i] = k
        else:
            k = p_next[k]
    return p_next

def KMP_algorithm(t,p):
    j, i = 0, 0
    n, m = len(t), len(p)
    p_next = get_next(p)
    while j < n and i < m:
        if i == -1 or t[j] == p[i]:
            j, i = j+1, i+1
        else:
            i = p_next[i]
    if i == m:
        return j-i
    return -1

# 测试
t = "abbcabcaabbcaa"  # 目标串
p = "abbcaa"  # 模式串
print(KMP_algorithm(t, p))

2、采用分治法求解最大连续子序列和问题

给定一个有n(n≥1)个整数的序列,要求求出其中最大连续子序列的和。
例如: 序列(-2,11,-4,13,-5,-2)的最大子序列和为20序列(-6,2,4,-7,5,3,2,-1,6,-9,10,-2)的最大子序列和为16。

解题思路:
分治法求最大连续子序列问题,可以先从序列的中间分开,分别求左序列和右序列的最大连续子序列,但是还需要考虑如果最大连续子序列正好越过序列的划分线的情况。如果最大连续子序列刚好越过划分线,那么它必然是左边最大连续子序列和右边连续最大子序列的和。所以我们只需要比较左边最大连续子序列,右边最大连续子序列,左边最大连续子序列加上右边最大连续子序列的和,从这三者中取最大值就可以求出整个序列的最大连续子序列。

代码:

def Max_zixulie(nums):
    n = len(nums)
    if n == 1:
        return nums[0]
    else:
        max_left = Max_zixulie(nums[0:n//2])
        max_right = Max_zixulie(nums[n//2:n])

    temp,max_leftsum = 0,0
    for i in range(n//2 - 1,-1,-1):
        temp = temp + nums[i]
        max_leftsum = max(temp,max_leftsum)
    temp,max_rightsum = 0,0
    for i in range(n//2,n):
        temp = temp + nums[i]
        max_rightsum = max(temp,max_rightsum)

    return max(max_left,max_right,max_leftsum + max_rightsum)

print(Max_zixulie([-2,11,-4,13,-5,-2]))

3、用分治策略求众数问题

问题描述:给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数。多重集S中重数最大的元素称为众数。要求对给定的又n个自然数的组成的多重集S,计算S的众数及其重数。

解题思路:
首先需要用分治策略解题,所以需要对元素进行排序,然后选取序列中间的元素,由它出发向前和向后寻找和它一样的元素,从而记录众数和重数。接下来从左侧和右侧分别继续递归比较,并在比较过程中判断是否大于已知的重数。在递归比较规程中,我们需要用众数比较剩下的左右剩余序列长度,如果众数大于等于左/右剩余序列长度,那么就不需要进行比较,直接输出就可以。

代码:

p, q = 0, 0
def ZhongShu(nums):
    n = len(nums)
    global p,q
    z_max,k_max,left,right = split(nums)
    if k_max > q:
        q = k_max
        p = z_max
    if left > q:
        ZhongShu(nums[0:left])
    if n - right > q:
        ZhongShu(nums[right:n])
    return p,q

def split(nums):
    n = len(nums)
    low, high = 0, n//2 + 1
    while low < n:
        if nums[low] == nums[n//2]:
            break
        else:
            low += 1
    while high < n:
        if nums[high] == nums[n//2]:
            high += 1
        else:
            break
    z = nums[low]
    k = high - low
    return z,k,low,high

print(ZhongShu([1,1,1,1,1,1,2,3,3,4,4,5,5,5,6,6,6,8,8,8,8,8,8,8]))

4、最近点对问题

设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。
(1)分别用蛮力法和分治法求解最近对问题;
(2) 分析算法的时间性能,设计实验程序验证分析结论。

(1)解题思路:
蛮力法直接用for循环遍历,对每两个点都做运算,并且比较记录最小值,最后输出最短距离和最近的点对。
分治方法在考虑了左、右两边各自的最近点对之后,还需要考虑是否会有最近的点对穿过了我们的划分线。这其实和寻找最长连续子序列有异曲同工之处,但是在考虑这个问题上,我们只需要从划分线向两侧分别延展已求的最近点对长度就可以,然后寻找在这个区域内的最近点对。

代码:(蛮力法)

def ManLi(nums):
    n = len(nums)
    x = float('inf')
    if n <= 1:
        return False
    for i in range(1,n):
        j = 1
        while j <= i:
            y = pow((nums[i][0] - nums[i - j][0]) ** 2 + (nums[i][1] - nums[i - j][1]) ** 2,0.5)
            x = min(x,y)
            if x == y:
                l = []
                l.append(nums[i])
                l.append(nums[i - j])
            j += 1
    return x,l[0],l[1]

print(ManLi([[0,4],[1,1],[1,5],[2,4],[3,2],[3,5],[4,0],[4,3],[5,2],[5,5]]))

代码:(分治法)

import sys
import math

def distance(x, y):
    return math.sqrt((x[0] - y[0]) ** 2 + (x[1] - y[1])** 2)

def FenZhi(points):
    n = len(points)
    if n < 2:
        return sys.maxsize, None, None
    elif n == 2:
        return distance(points[0], points[1]), points[0], points[1]

    points = sorted(points)
    half = (n - 1) // 2
    d1, a1, b1 = FenZhi(points[:half])
    d2, a2, b2 = FenZhi(points[half:])
    d, a, b = (d1, a1, b1) if d1 < d2 else (d2, a2, b2)
    calibration = points[half][0]
    left, right = [], []
    for u in points:
        if calibration - d < u[0] < calibration:
            left.append(u)
        elif calibration <= u[0] < calibration + d:
            right.append(u)

    right = sorted(right, key=lambda x: (x[1], x[0]))
    res = d
    for u in left:
        l, r = -1, len(right) - 1
        while r - l > 1:
            m = (l + r) >> 1
            if right[m][1] <= u[1] - d:
                l = m
            else:
                r = m
        idx = r
        for j in range(7):
            if j + idx >= len(right):
                break
            if distance(u, right[idx + j]) < res:
                res = distance(u, right[idx + j])
                a, b = u, right[idx + j]

    return res, a, b

print(FenZhi([[0,4],[1,1],[1,5],[2,4],[3,2],[3,5],[4,0],[4,3],[5,2],[5,5]]))

(2)蛮力法用了两个循环,因而其时间复杂度是 O ( n 2 ) O(n^2) On2,分治法由公式有 T ( n ) = T ( n / 2 ) + O ( n ) T(n) = T(n/2) + O(n) T(n)=T(n/2)+O(n),由主定理可以得出其时间复杂度是 O ( n l o g n ) O(nlogn) Onlogn

通过设置100,1000,10000个随机点对,测试蛮力策略和分治策略的用时,从而比较各自的时间复杂度。

image-20240403173629934

实验结果如下:

image-20240403173541725

由此可见蛮力法的时间大致沿着 n 2 n^2 n2的速率增长,而分治法大致沿着 n l o g n nlogn nlogn增长,符合我们的计算结果。

六、实验小结(包括问题和解决方法、心得体会等)

本次作业是分治算法的一个应用,分治和递归相辅相成,通过编写分治算法,让我深刻了解了递归的含义,并且熟悉应用了分治算法解决问题。
串匹配问题是我们在数据结构中就遇到的老朋友,其中的BF算法思想很简单,就是蛮力策略,而KMP算法主要思想是减少重复比较的时间,所以定义了一个next的方法,用来寻找最长前后缀,从而达到不移动主串,只移动子串的快速匹配。
寻找最长连续子序列问题,难点在于想到如果所求序列正好被划分的情况,而后续在三个值中寻找最大值不难分析。
分治策略求众数也是很典型的分治策略的应用,但是和上一题不一样,我们需要先行找到当前最大的众数,然后再应用递归到左、右两个序列中。
最近点对问题应该是最有难度的一道题,蛮力策略很简单,但是分治方法在考虑了左、右两边各自的最近点对之后,还需要考虑是否会有最近的点对穿过了我们的划分线。这其实和寻找最长连续子序列有异曲同工之处,但是在考虑这个问题上,我们只需要从划分线向两侧分别延展已求的最近点对长度就可以,然后寻找在这个区域内的最近点对。
通过本次作业,我对算法有了更进一步的认知,也锻炼了我的编程能力。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker安装mysql并且设置主从

Docker安装部署mysql 下载镜像 docker pull mysql:5.7.35查看镜像 docker images启动 直接启动不挂载文件 docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD123456 -d mysql:5.7.35挂载文件 docker run -p 3306:3306 --name mysql \ -v /usr/local/docker/m…

正则表达式与JSON序列化:去除JavaScript对象中的下划线键名

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

【Java EE】关于Maven

文章目录 &#x1f38d;什么是Maven&#x1f334;为什么要学Maven&#x1f332;创建⼀个Maven项目&#x1f333;Maven核心功能&#x1f338;项目构建&#x1f338;依赖管理 &#x1f340;Maven Help插件&#x1f384;Maven 仓库&#x1f338;本地仓库&#x1f338;私服 ⭕总结 …

STM32G系 编程连接不上目标板,也有可能是软件不兼容。

由于一直用的老版本STM32 ST-LINK Utility 4.20 &#xff0c;找遍了所有问题&#xff0c;SWD就是连不上目标板。 电源脚 VDDA 地线&#xff0c;SWD的四条线&#xff0c;还是不行&#xff0c;浪费了一天&#xff0c;第二天才想起&#xff0c;是不是G系升级了 SWD协议。结果下载…

从汇编看函数调用

文章目录 函数调用流程栈相关寄存器及的作用简介寄存器功能指令功能 栈函数的括号{}正括号反括号 参数传递传值&#xff0c;变量不可改传指针&#xff0c;变量可改C 传引用 函数调用实例 函数调用流程 目标&#xff1a;函数调用前后栈保持不变 保存main函数的寄存器上下文移…

【HTML】简单制作一个3D动画效果重叠圆环

目录 前言 开始 HTML部分 CSS部分 效果图 总结 前言 无需多言&#xff0c;本文将详细介绍一段代码&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建两个文本文档&#xff0c;其中HTML的文件名改为[index.html]&#xff0c;CSS的…

Tensorflow2.0笔记 - 自定义Layer和Model实现CIFAR10数据集的训练

本笔记记录使用自定义Layer和Model来做CIFAR10数据集的训练。 CIFAR10数据集下载&#xff1a; https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 自定义的Layer和Model实现较为简单&#xff0c;参数量较少&#xff0c;并且没有卷积层和dropout等&#xff0c;最终准确率…

Java—抽象方法与接口

声明&#xff1a;以下内容是根据B站黑马程序员的Java课程&#xff0b;博主自己的理解整理而成&#xff0c;课程很好&#xff0c;适合初学者学习。 关于此类题目&#xff0c;重要的是识别出用什么来实现&#xff0c;到底是接口还是抽象方法&#xff0c;还是共有的属性等等&…

医用三维影像PACS系统源码 一套成熟的PACS系统应具备哪些核心要素?

医用三维影像PACS系统源码 一套成熟的PACS系统应具备哪些核心要素&#xff1f; PACS及影像存取与传输系统”( Picture Archiving and Communication System)&#xff0c;为以实现医学影像数字化存储、诊断为核心任务&#xff0c;从医学影像设备&#xff08;如CT、CR、DR、MR、…

ZZS-7/1G212分合闸电源综合控制装置 220VAC 板前接线 JOSEF约瑟

系列型号&#xff1a; ZZS-7G/1分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7G/11分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7G/23分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7G/24分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7/1G11分闸、合闸…

21.兼容性测试

考试频率低&#xff1b; 一般考兼容性测试会结合web测试&#xff1b;&#xff08;兼容性矩阵&#xff09; 主要议题&#xff1a; 1.兼容性测试概述 2.硬件兼容性测试 最低配置不讲究工作负载&#xff0c;意思是软件能够运行的最低要求环境&#xff1b; 推荐配置&#xff0c…

修复503 Service Unavailable Error问题

近期我们网网站经常出现503 Service Unavailable Error&#xff0c;在此之前我们的网站从未出现过这种问题&#xff0c;我们向虚拟主机提供商Hostease咨询后&#xff0c;了解到503 Service Unavailable错误是指服务器暂时无法处理请求&#xff0c;通常是由于服务器过载、维护、…

Python数据结构与算法——数据结构(链表、哈希表、树)

目录 链表 链表介绍 创建和遍历链表 链表节点插入和删除 双链表 链表总结——复杂度分析 哈希表(散列表) 哈希表介绍 哈希冲突 哈希表实现 哈希表应用 树 树 树的示例——模拟文件系统 二叉树 二叉树的链式存储 二叉树的遍历 二叉搜索树 插入 查询 删除 AVL树 …

路由Vue-Router使用

Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成&#xff0c;让用 Vue.js 构建单页应用变得轻而易举。 介绍 | Vue Router (vuejs.org) 1. 安装 npm install vue-router4 查看安装好的vue-router 2. 添加路由 新建views文件夹用来存放所有的页面&#xff0c;在…

初入职,如何用好 git 快速上手项目开发

前言 介绍在工作中使用 git 工具 文章目录 前言一、git 简介1、是什么作用操作3、用途 二、基本概念1、工作区2、暂存区3、版本库4、操作过程 三、基本命令操作 一、git 简介 1、是什么 git 是一个方便管理代码版本的工具&#xff0c;用一个树结构来维护和管理所有的历史版本…

数据结构记录

之前记录的数据结构笔记&#xff0c;不过图片显示不了了 数据结构与算法(C版) 1、绪论 1.1、数据结构的研究内容 一般应用步骤&#xff1a;分析问题&#xff0c;提取操作对象&#xff0c;分析操作对象之间的关系&#xff0c;建立数学模型。 1.2、基本概念和术语 数据&…

Finite Element Procedures K.J.Bathe 【教材pdf+部分源码】|有限元经典教材 | 有限元编程

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

flask的使用学习笔记1

跟着b站学的1-06 用户编辑示例_哔哩哔哩_bilibili flask是一个轻量级&#xff0c;短小精悍&#xff0c;扩展性强&#xff0c;可以扩展很多组件&#xff0c;django大而全 编程语言它们的区别&#xff1a; (这些语言都很了解&#xff0c;java和python是高级语言&#xff0c;都…

动手做一个最小Agent——TinyAgent!

Datawhale干货 作者&#xff1a;宋志学&#xff0c;Datawhale成员 前 言 大家好&#xff0c;我是不要葱姜蒜。在ChatGPT横空出世&#xff0c;夺走Bert的桂冠之后&#xff0c;大模型愈发地火热&#xff0c;国内各种模型层出不穷&#xff0c;史称“百模大战”。大模型的能力是毋…

UE4几个常用节点链接

UE4几个常用节点链接 2017-12-02 12:54 1. 流光材质(及uv平铺次数) 2. 跑九宫格 3.闪光3。1 粒子闪烁效果 4.图案重复5.平移扭曲 6.溶解 刀光的uv滚动图片源或采样节点属性里改成clamp无后期发光光晕anistropic 各向异性高光法线图 法线图叠加 blendangle orrectedNo…