SciTech-BigDataAIML-Algorithm-Heuristic启发式 最优化算法

所有的Heuristic(启发式)算法 的 “精髓” 在于对“Context(上下文)”的精准“计算、估计和预测”;

每一种算法都有其最适用的场景,算法的设计、选取 应当适配 场景;

非常好的“斯坦福大学”计算机科学毕业生的网站

Amit Patelamitp@cs.stanford.edu

很好的游戏算法+编程网:

https://www.redblobgames.com/pathfinding/a-star/introduction.html

  • KMP字符串匹配算法
  • Dynamic Planning动态规划
  • Dijkstra迪杰斯特拉算法
  • A*算法
  • Floyd(弗落伊得)最短路线算法
  • Prim算法

KMP字符串匹配算法

def kmp_search(string, patt):
"""signature: 字符串匹配算法: 在<string>,搜索<pattern>""" patt_len = len(patt)
cmp_len = len(string) - patt_len + 1
next = build_next(patt) # next数组的数值,代表"当前字符"匹配"失败"时,"可跳过"的"匹配字符个数".
i = 0 # string 的指针: 只增不减,同时 pattern 的指针还可以预先偏移比较,是KMP的精华
j = 0 # pattern 的指针 while i < cmp_len : # 注意: i 只增不减, KMP算法的精华
if string[i] == patt[j]:
# 字符匹配成功:
i+= 1 # string 指针前移一个
j+= 1 # pattern 指针前移一个
elif j > 0:
# 字符匹配失败: 之前有匹配成功的不只一个字符,next匹配时, 可跳过"上一次"匹配过的“那一部分”
j=next[j-1] # pattern 指针退一字符, 停在最长匹配的字符上; 跳过pattern的前面一些子串. KMP精华
else:
# 字符匹配失败: 第一个字符就失配,只将"string"指针前移一个字符
i+= 1 # string 指针前移一个字符. if j== patt_len: # 匹配成功: 当指针 j 等于 pattern 长度
print(string)
print("%s%s" % (' '*(i-j), patt))
return i-j # 退出. return (i-j) def build_next(patt):
"""
预先计算构造出Next数组: PMT(Partial Match Table, 部分匹配表)
用pdb 的step debug调试 build_next("ababcdabak"), 就对PMT的构造有最深刻的认知.
"""
# next数组的数值,代表"当前字符"匹配"失败"时,"可跳过"的匹配字符个数".
prefix_len = 0 #当前共同"前后缀"的长度
next = [0] #next数组,初始时第一个元素的0
k=1
while k< len(patt):
if patt[prefix_len] == patt[k]:
prefix_len+=1
next.append(prefix_len)
k+=1 # k 前移一个字符
else:
if prefix_len==0:
# 前一个字符不同;
next.append(0)
k+=1 # k 前移一个字符
else:
# **k不变**,**只改变 prefix_len**, 可能经过好几次的iteration, 才能得出要插入next数组的最终数值.
# 当: k 由增加态, 首次转为0时,总之, 分两类情况:
# prefix_len=1, 例如 pattern = "ABCBAK",
# 当k=5时, 先prefix_len=1, 当前k位"反溯 prefix_len 个字符"的 "AK", 与 头部的 "AB"的"偏移"同;
执行next step后, 有prefix_len=next[0]=0,
# prefix_len>1, 例如 pattern = "AACAAK",
# 当k=5时, 先prefix_len=2, 当前k位"反溯 prefix_len 个字符"的 "AAK", 与 头部的 "AAB"的"偏移"同;
执行next step后, 有prefix_len=next[1]=1
prefix_len=next[prefix_len-1] # KMP的精华;
return next s = "ABABABCAA"
p = "ABABC" def print_next(patt):
print(build_next(patt)) # 用pdb 的step debug调试 build_next("ababcdabak"),
# 就对 next数组(PMT)的构造有最深刻的认知.
# In [9]: print_next("ababcdabak")
# [0, 0, 1, 2, 0, 0, 1, 2, 3, 0]

KMP 字符串匹配算法:

  • KMP算法的时间复杂度为$ O(n+m)$
  • 源于 Knuth, Morris, Pratt 三位大神的一篇论文"FAST PATTERN MATCHING IN STRINGS".



BFM(Brute Force Matching)

先引入BFM(Brute Force Matching, 暴力匹配):

  • BFM算法的时间复杂度为$ O(n * m)$
  • 即在<str>搜索<pattern>,

    由第一个字符开始一个个字符的与<pattern>比较,完全匹配上则return;

    如果不完全匹配,则跳到下一个字符,重新一个个字符与<pattern>比较。

    直到比较完成<str>的所有可能。

KMP( KMP Fast Pattern Matching)

KMP 快速匹配算法的思路是,不用BFM算法的"backup(回退)":

在匹配某一个字符时,

既然字符串在比对失败的时候,我们已经知道都读取比对过哪些字符序列,

有没有可能避兔backup(回退)到下一个字符,重新匹配”的步骤?

KMP 匹配实例

假设"string"为"ABABABCAA", 查找的"pattern"为"ABABC":

  • KMP匹配可能的最大长度字符串时: (i, j)指针对, 历经匹配的(0,0), (1,1), (2,2), (3,3),





  • KMP 匹配某一个字符, 字符串在比对失败时:

    • 到(i, j) 为 (4,4) 时,"pattern"出现第一个“不匹配字符”, 此时 j = 4,

    • 设置pattern头部"偏移": j=next[j-1], 偏移量可能值的情况是

      • j = 0, 当 都可能将"j"设置为0,即对 string 的 i 处的字符与 pattern 的首个字符开始,一一比较.
      • 0 < j < n, 当 pattern为一个字符重复出现 n次时, j 取得最大值:n-1

      本例是 j=next[j-1]=next[3]=2

      此时 j = 2, 同时 i=4(i不变)

    • 注意: 整个查找过程, i都是只向前移动,而pattern头部的“偏移量”根据"匹配情况"动态设置为[0, n)

      这是 KMP算法的两个最大特点

  • KMP 匹配某一个字符, 可以只 "Partial matching"(上一步比较过, 并且有Partial matched)跳过matched的部分:



    在本例:

    • 即"AB"已经在上一次时匹配过的LCS(Longest Common Substring, 最长匹配substr),本次可以跳过Partial;
    • 跳过"上一次匹配"过的"Partial matched", 是通过设置"本次匹配"的"pattern头部"的"偏移量"实现(string指针不变).
    • 实现上: 由pattern预先build的next数组, 取出"本次匹配"可"预先跳过比较"的"最长pattern字符数".
    • 源码:此时 string 指针 i 不变, 只要 pattern 指针设置成 j=next[j-1]( 因为j>0 ).

  • Papers: 下载 Knuth/Morris/Pratt 的Paper论文:

    ACM(Association for Computing Machinery) of the USA.

    https://dl.acm.org/doi/abs/10.1137/0206024

    多读和写论文绝对有好处:

Dynamic Planning动态规划

Dynamic Planning/Programming:

动态规划是计算机解决最优化问题的一种方法; 他给我们的印象是效率高、速度快。

  • 首先我们来看一个经典的“动态规划问题”:

    • 给一个无序数组,找出所有"最长递增子序列":

      举例: 无序数组$ nums=[1,5,2,4,3] $ 的 最长递增子序列: 一个是$ [1,2,4] \(, 另一个是\) [1,2,3] $

    • 我们可以进一步简化这个问题:

      只要算法求出"最长递增子序列"的长度就好;

    • 枚举(普通解法):

      • 试验+探索:枚举代表性的一组数据(cases), 画出其"Recursion Tree":

      • 理论设计: 写出其"Recursion Function", 用"科学方法"在"理论上"评估算法性能(时间复杂度, BigO Notion)":





    • 理论优化:

      • Pruning(剪枝)





      • 记忆化搜索:













      • 工程优化,将Recursion Method改写成 Iteration Method方式:

        Iteration Method可以 释放对 Stack memory的占用,将"动态的内存需求"调整到用Heap memory满足:

    • 最终评估: 用"科学方法"在"理论上"评估算法性能(时间复杂度, BigO Notion)"

  • 扩展:

A *(Star) Algorithm(A星算法):

amitp@cs.stanford.edu

很好的游戏算法+编程网:

https://www.redblobgames.com/pathfinding/a-star/implementation.html

Loss Function: TotalCost="NewCost + PredicativeCost"

计算"总体的Cost": 包括一部分的"NewCost(已用成本)",和另一部分的"Predicative(预测成本)";

在对"predicative future cost(预测的将来成本)"的估计,和评估 TotalCost(总体成本)这些方面,

A *(Star) Algorithm(A星算法) 要优于 只计算 best next cost的Dijkstra(迪杰斯特拉算法)。

这是 A *(Star) Algorithm 多数时间 优于 Dijkstra Algorithm 的 root cause;

但是 Dijkstra Algorithm 的计算量小、算法精简。

1解决游戏的自动路线规划 2算法图示 3对比多种

主体实现

def heuristic(a, b):
# Manhattan distance on a square grid
return abs(a.x - b.x) + abs(a.y - b.y) def a_star_search(graph,start,goal):
frontier=PriorityQueue()
frontier.put(start,0)
came_from = {start:None}
cost_so_far ={start:0} while not frontier.empty():
# 由"优先队列"抽取出"总代价最低"(new_cost+heuristic(goal,next))的node
current=frontier.get()
if current= goal:
break for next in graph.neighbors(current):
new_cost = cost_so_far[current] + graph.cost(current,next)
if next not in cost_so_far and new_cost < cost_so_far[next]:
came_from[next]=current
cost_so_far[next] = new_cost
# 将next的node及其"总代价"插入"优先级队列"
frontier.put(next, new_cost+heuristic(goal,next)) return came_from, cost_so_far











Floyd(弗落伊得)最短路线算法

Prim算法

SciTech-BigDataAIML-Algorithm-Heuristic启发式 最优化算法: KMP字符串匹配 + A*(star)+ Prim + Dynamic Planning动态规划 + Floyd(弗落伊得)最短路线的更多相关文章

  1. Luogu 3375 【模板】KMP字符串匹配(KMP算法)

    Luogu 3375 [模板]KMP字符串匹配(KMP算法) Description 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来 ...

  2. 洛谷—— P3375 【模板】KMP字符串匹配

    P3375 [模板]KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next. (如 ...

  3. 洛谷P3375 [模板]KMP字符串匹配

    To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...

  4. P3375 【模板】KMP字符串匹配

    P3375 [模板]KMP字符串匹配 https://www.luogu.org/problemnew/show/P3375 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在 ...

  5. KMP字符串匹配 模板 洛谷 P3375

    KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...

  6. {Reship}{KMP字符串匹配}

    关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827

  7. 洛谷P3375 - 【模板】KMP字符串匹配

    原题链接 Description 模板题啦~ Code //[模板]KMP字符串匹配 #include <cstdio> #include <cstring> int cons ...

  8. P3375 模板 KMP字符串匹配

    P3375 [模板]KMP字符串匹配 来一道模板题,直接上代码. #include <bits/stdc++.h> using namespace std; typedef long lo ...

  9. KMP字符串匹配学习

    KMP字符串匹配学习 牛逼啊 SYC大佬的博客

  10. Java实现 蓝桥杯 算法提高 字符串匹配

    试题 算法提高 字符串匹配 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行.你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符:当选项关闭时 ...

随机推荐

  1. 【记录】Opencv+LibTorch安装

    环境Ubuntu20.04. [Opencv]源码编译:Linux系统下opencv3.4.1安装教程 [LibTorch]下载已编译版本:在Ubuntu下安装LibTorch [磁盘空间不足]vmw ...

  2. 高性能深度学习推理引擎 -- OpenPPL

    OpenPPL OpenPPL是商汤基于自研高性能算字库的开源深度学习推理平台,能够让人工智能应用高效可靠地运行在现有的CPU/GPU等计算平台上,为云端场景提供人工智能推理服务 OpenPPL基于全 ...

  3. 操作系统:设备I/O -- 设备如何处理内核I/O包

    上一讲实现了建立设备的接口,相当于制定了部门的相关法规,只要遵循这些法规就能建立一个部门.一个部门的职责不难确定,它应该能对上级下发的任务作出响应,并完成相关工作,而这对应到设备,就是如何处理内核的I ...

  4. AI模型的回调能力的理解和实现

    前言 BigTall最近把RAG和Agent的原理想通了,对于"一切都是提示词"的理解又更多了一些.本文把我的理解大致整理了一下,给出BigTall自己的一个实验.希望能够对大家有 ...

  5. Got bad greeting from SMTP host: smtp.163.com, port: 465, response: [EOF]

    在Spring Boot项目中,使用org.springframework.mail.javamail.JavaMailSender发送邮件抛异常,异常信息: Mail server connecti ...

  6. 记录一次自己用 AI 写IOS APP的经历

    我是几乎没有移动端开发经验的.仅有的一点安卓开发经验还是十几年前没毕业的时候自己瞎折腾. 故事的起源是每天辅导我儿子功课时的暴跳如雷. 我儿子上一年级了,在语文的生词上落后得非常严重(当然可能是他同学 ...

  7. 解决DevToolsActivePort file doesn't exist

    今天遇到个小问题:selenium 启动 chrome crash,报错:DevToolsActivePort file doesn't exist. 在option中添加一下几行: option = ...

  8. c#格式化字符串 toString()

    1.使用 ToString 方法的默认格式设置 public class Automobile { public string Name { get; set; } = "小王"; ...

  9. 「Log」2023.8.25 小记

    序幕 到校同学都没来,先摆. 写博客,写啊,写啊. 改费用流板子. \(\color{royalblue}{P3381\ [模板]最小费用最大流}\) 板子. 痛心疾首,建边的时候费用边反边为负权边. ...

  10. Go标准库Cond

    Go标准库的Cond Go 标准库提供 Cond 原语的目的是,为等待 / 通知场景下的并发问题提供支持.Cond 通常应用于等待某个条件的一组 goroutine,等条件变为 true 的时候,其中 ...