首页 > 其他分享 >KMP与自动机

KMP与自动机

时间:2023-11-23 21:03:45浏览次数:35  
标签:主串 匹配 xyz next KMP 自动机 失配

KMP 与 AC自动机

都是字符串匹配
KMP是单模匹配
ac自动机是多模匹配

KMP原理

例子

当我们匹配字符串A(长度为n)中是否有B(长度为m, m<n)的时候
比如:

  • A
    ABCDABCDEF
  • B
    ABCDE

一个朴素的思路是暴力, 复杂度当然是O(n * m)
KMP就是一个优化的算法
KMP的理论基础就是, 并不是每次匹配往后跳一位. 而是跳多位(>=1).
当匹配到ABCD, 发现下一位并不是E的时候, 我们可以直接跳到下一个ABCD, 主串和模式串都可以不需要从头开始比较. 这个优化是不是很直观

为什么可以这么做呢? 因为比如逐位比较到第k位的时候, 前k-1个字符是我们已知的. 如果我们能利用这个信息就好了! 事实上我们确实可以利用这个信息

如何做

这实际上是一个dp
一个状态转移

我们假设主串是
a b c d e f g h i j k
而模式串是x y z w
继续假设此时我们已成功匹配了两个字符, a == x, b == y, c == z, 但是第4个字符 w != d

  1. 想要往后跳
    此时我们想要跳, 往后跳尽量远的距离, 就可以尽量降低复杂度
  2. 怎么跳
    一个朴素的想法是跳到下一个"a b c" 连接的地方, 既然这个"a b c"处失配了, 那就跳到下一个, 然而, 这种思路其实就是一个一个的朴素匹配. 预处理的时间跟直接朴素匹配一样, 都是无法接受的.
    那咋办嘛. 所以这里重点不是如何预处理主串, 因为我们算法实际上是在主串跑的, 预处理主串的复杂度是我们无法接受的.
    主串一定是和子串匹配失败时候才需要跳, 那就意味着至少有一段(0<=len<m)的部分是和子串前len部分是一致的, 这样就有了操作的空间. 于是很直接地想到了预处理子串. 有什么比只需要处理m长度的串就可以进行跳跃更有性价比呢?
  3. 跳的思路
    现在的已知信息就是, 在主串的[x, x + len)的串和子串的[0, len)是一致的
    跳跃是产生在主串上的
    这时候又可以回到刚才朴素的想法了, 我失配了, 我想尽量往后跳啊,
    s = "xyz" 匹配成功, 尽量往后跳的话, 我会想在主串里找到下一个"xyz", 然后从那里继续跟子串的第一个"xyz"对齐, 继续比较
    可根据刚才说的, 我们现在只拥有子串的预处理结果. 而当前根据我们的已知信息,
    主串的xyz的串和子串的xyz是一致的
    这有个毛线用 (- _ -) , 我们完全无法找到下一个"xyz"在哪
    故而, 我们可以发现, 既然要找第二个一样的string, 匹配里就要有重复的string, 这样才行

  4. 现在我们重新假设现在的匹配是这样的:
    主串:
    "x y z x y ? x y z x y w"
    模式串:
    "x y z x y w"
    当'?'和'z'失配的时候, 已匹配的部分是"x y z x y", 失配的部分是 '?' != 'w'
    是不是可以跳?
    有重复的吧?
    是不是主串可以从第二个"x y"跳到第一个"x y"?
    和不现实的预处理主串相比, 是不是就是把朴素跳跃思路放到了预处理模式串上?
  5. 为什么要跳最长公共前后缀
    再假设是这么一个串
    主串:
    "x y z x y t ? x y z x y t w"
    模式串:
    "x y z x y t w"
    和刚才相比多了个t
    跳跃的时候怎么跳? "x y"可以直接跳第二个"x y"吗?
    no! no! no! だめ!
    可以注意到, xyt 和 xyz 已经是无法匹配状态了, 所以跳的毫无意义
    同理, x 和 x 也没法跳, y 和 y 也没法跳
    这下明白为什么next数组是 最长相同前后缀 了吧?
    因为前后缀在无法跳(没有相同前后缀)的情况下, 其他相同的可以证明是无法跳的
    而当前后缀可以跳的时候, 则一定是最优跳法, 比如xyxyx, 跳个xyx不比跳个单独的x更优吗

next数组的计算

朴素思路起手
i属于[0, m), 对于每一个区间[0, i]
暴力双指针指向两边, 匹配一遍

实际上这里有一个优化, 比较难想, 是依赖于对称性的
其实是这样的
首先, 朴素匹配的基础是没问题的. 大部分case遇不到相等于第一个元素的case直接就越过去了, next是-1
一旦进入next有非-1值的情况, 也就是我们就可以依赖于前一个求出来的next状态的情况
举个例子就是"abc??abc", 计算最后一个c的时候其实就可以基于ab已经匹配的状态+1, 1+1 = 2直接出答案
而再来个case, 当失配的时候怎么搞
s = "ababc??ababz"
这里是从第6个字符直接开始匹配的, 而z和c失配了, 并不是直接从头再来, 而是从前一个"b"的next来, 注意这里的b指的是s[3]的那个'b', 因为后面的b的next存的肯定是3不是么...
而s[3]的b的next就回滚到了第一个"ab", 意识到了吗, 截短了, 既然"ababz"不匹配"ababc", 那就用"abz"去尝试匹配"aba", 不成功就继续回滚
在有大量重复子串的数组里, 这样处理可以显然提高效率, 类似的技巧还出现在manacher求回文串里

自动机

ac自动机是用tire树
加了个失配指针, 原理很类似, 多模匹配的这些目标串, 前缀相同的越多, 匹配起来越容易
我没仔细看回文自动机, 感觉原理应该也类似?

标签:主串,匹配,xyz,next,KMP,自动机,失配
From: https://www.cnblogs.com/ryougi/p/17852472.html

相关文章

  • KMP模板
    #include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintN=1e3+10,inf=0x3f3f3f3f;intnex[N];//nex[j]的意思是当子串的第j个字符和主串的第i个字符不匹配时,我们应该从子串的nex[j]字符开始重新匹配stringa,b;/*kmp指针回退j=nex[j-1]......
  • 「笔记」回文自动机
    目录写在前面结构构造复杂度证明模板题代码写在最后写在前面其实这东西学名叫EERTree,PalindromicTree,直译是回文树,但本质上是一类有限状态自动机所以也可以叫PalindromicAutomaton,因为我很喜欢自动机所以以下都叫它回文自动机。结构类似后缀自动机的,回文自动机(以下简称P......
  • 扩展 KMP——Z 函数
    本文下标从\(0\)开始。建议:前置知识。扩展KMP(Z函数)我们已经认识了前缀函数了。它是维护一个字符串的所有前缀的最长公共真前后缀的长度——\[\overbrace{s_0\dotss_{\pi(i)-1}}~s_{\pi(i)}\dotss_{i-\pi(i)}~\overbrace{s_{i-\pi(i)+1}\dots\color{red}s_i}~s_{i+1}......
  • kmp算法
    2023-11-14作用:从一个字符串中找到另一个字符串的位置思路:    暴力匹配-》主串的指针一直往前走,不后退-》匹配串的指针回退的位置变小-》根据前缀表 求前缀表(匹配串的所有前缀的最长公共前后缀长度表):/求前缀表int[]next=newint[needle.length()];......
  • RKMPP 硬编码之mpi_enc_test .c解析
    一.简介mpi_enc_test是rockchip官方编码demo本篇文章进行mpi_enc_test的代码解析,编码流程解析二.环境介绍硬件环境:ArmSoM-W3RK3588开发板软件版本:OS:ArmSoM-W3Debian11三.mpp编解码流程解析<center>图3.1RKMPP编码器接口为用户提供了输入图像数据,输出码......
  • 亚马逊云科技如何完善自动机器人及大语言模型的问答回复准确度
     概述 客户联络中心在现代是构成一个完整企业的重要组成部分,作为企业与顾客的连接纽带,在销售、服务支持以及提升顾客满意度方面发挥着至关重要的作用。使用亚马逊云科技AmazonConnect出海企业可以快速搭建自己的全球客服联络中心。当前客服联络中心也面临诸多的挑战,如长时间的电......
  • 字符串匹配算法:KMP
    Knuth–Morris–Pratt(KMP)是由三位数学家克努斯、莫里斯、普拉特同时发现,所有人们用三个人的名字来称呼这种算法,KMP是一种改进的字符串匹配算法,它的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。它的时间复杂度是O(m+n)字符匹配:给你两个字符......
  • AI问答:关于字符串匹配算法的区别及应用场景,哈希/kmp/字典树/AC自动机
    1. 哈希(Hashing):哈希是一种将字符串转换为唯一标识符的技术,通常用于字符串的快速查找和比较。实现难度相对较低,但需要处理哈希冲突的问题。哈希在处理大量数据的查找和比较问题时非常实用。2. KMP(Knuth-Morris-Pratt):KMP 是一种用于字符串匹配的算法,特别适用于查找子串在主串中的......
  • 串 - KMP算法
    数据结构算法中重中之重。肯定考。  针对该算法,ShoelessCai打算用几个问题来梳理清楚:1.算法返回什么?返回的是主串的位置i2.算法输入什么?主串、模式串(较短的)、Next数组(记录模式串位置)3.基本思想:如果匹配失败的时候,从失败位置,往前搜索,有多少个字符SLOTS是一致的?......
  • HanLP — Aho-Corasick DoubleArrayTire 算法 ACDAT - 基于双数组字典树的AC自动机
    双数组字典树能在O(1)(1是模式串长度)时间内高速完成单串匹配,并且内存消耗可控,然而软肋在于多模式匹配。如果要匹配多个模式串,必须先实现前缀查询,然后频繁截取文本后缀才可多匹配。比如ushers、shers、hers…这样一份文本要回退扫描多遍,性能较低。既然AC自动机的goto表本身就是一......