KMP算法 - 确定有限状态自动机

news2024/10/6 12:20:26

KMP神在哪里?

子串匹配问题,拍脑袋一下子想出来的暴力解法大抵都是两重for循环,不断重复扫描主串,与子窜进行匹配,重复换句话讲就是冗余,会有很高的时间复杂度

我先前博客大作业发的模糊查找算法就是如此,我那里是在计算一个匹配度的问题,通过相同定位到相同字母判定开始计算相同字母的个数作为匹配度,多个判定点时,最终取最值。

而KMP通过对子串分析得到一个DFA(确定有限状态自动机)数组(后面简称dp数组),可以实现“移动”子串来与主串进行匹配,时间复杂度只需 O(N),也就是说只用遍历一遍主串!

关于DFA数组

什么是状态机

状态机(一般指有限状态机或有限状态自动机)是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型

状态机中有几个术语:state(状态) 、transition(转移) 、action(动作) 、transition condition(转移条件) 。

  • state(状态) :将一个系统离散化,可以得到很多种状态,当然这些状态是有限的。例如:门禁闸机可以划分为开启状态、关闭状态;电扇可以划分为关、一档、二档、三档等状态。

  • transition(转移) :一个状态接收一个输入执行了某些动作到达了另外一个状态的过程就是一个transition(转移)。定义transition(转移)就是在定义状态机的转移流程。

  • transition condition(转移条件) :也叫做Event(事件),在某一状态下,只有达到了transition condition(转移条件),才会按照状态机的转移流程转移到下一状态,并执行相应的动作。

  • action(动作):在状态机的运转过程中会有很多种动作。如:进入动作(entry action)[在进入状态时进行]、退出动作(exit action)[在退出状态时进行]、转移动作[在进行特定转移时进行]。

DFA状态机

我们这里的dp数组就是一个状态机

=> 二维数组 dp[ 状态 ][ 对应到子串中的字符时 ] = 转移到下一个状态

这里的“转移到下一个状态”就是对上面说的“移动”子串来匹配主串的实现

dp[j][c] = next
0 <= j < M,代表当前的状态
0 <= c < 256,代表遇到的字符(ASCII 码)
0 <= next <= M,代表下一个状态

dp[4]['A'] = 3 表示:
当前是状态 4,如果遇到字符 A,
pat 应该转移到状态 3

dp[1]['B'] = 2 表示:
当前是状态 1,如果遇到字符 B,
pat 应该转移到状态 2

如何构建Transition

下图为一个pat = “ABABC”的子串的状态转移图的构建

难点在于怎么让状态机确定回退到之前的哪个状态?

KMP算法强就强在它能尽可能少的回退

如何尽可能少的回退

我们记录一个X状态来标记遇到具体字符后 => 需要回退时,回退到哪个状态

这里对于X状态的标志有点动态规划的思想在里面 => 因为都是根据已知状态来得到新状态

X状态的更新很像匹配子子串

=> X也在匹配子串,X状态此刻匹配出的子串  具有  j状态此刻匹配出来最长相同部分(前缀)

甚至,还可以这样去理解X状态:有点像笔记本或备忘录,遇到类似情况可以复用些什么东西。这里就很像动态规划里的Memo

#include <bits/stdc++.h>
using namespace std;

class KMP {
private:
    vector<vector<int>> dp;
    string pat;

public:
    KMP(string pat) {
        this->pat = pat;
        int sizePat = pat.size();
        dp.resize(sizePat, vector<int>(256, 0));
        int X = 0;
        dp[0][pat[0]] = 1;
        for(int j = 1; j < sizePat; j++) {
            for(int c = 0; c < 256; c++) {
                dp[j][c] = dp[X][c];
            }
            dp[j][pat[j]] = j + 1;
            X = dp[X][pat[j]];
        }
    }

    int Match(string txt) {
        int sizeTxt = txt.size(), sizePat = pat.size();
        int j = 0;
        for(int i = 0; i < sizeTxt; i++) {
            j = dp[j][txt[i]];
            if(j == sizePat) return i - sizePat + 1;
        }
        return -1;
    }
};

int main() {
    string pat, txt;
    cin >> txt >> pat;
    int index = KMP(pat).Match(txt);
    cout << index;
    return 0;
}

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

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

相关文章

三分钟告诉你如何和智能ai聊天

有一个名叫艾丽的年轻女孩&#xff0c;她生活在一个科技发达的未来世界。在这个世界里&#xff0c;人们与人工智能伙伴共同生活。艾丽对ai技术充满好奇&#xff0c;尤其是对ai对话聊天工具的运作方式。为了知道ai对话聊天工具怎么用&#xff0c;艾丽决定展开探索。 方案一&…

智能无线监测器的工作原理及应用优势

在现代工业生产中&#xff0c;设备状态监测对于确保生产的安全性、效率和可靠性至关重要。随着科技的不断发展&#xff0c;智能无线监测器成为工业设备状态监测的利器。本文将介绍智能无线监测器在工业领域中的应用&#xff0c;以及其带来的优势和价值。 图.设备状态监测&#…

智驾风向标|卷、乱、难,如何穿越多极分化新周期?

竞争越来越卷&#xff0c;企业越来越难&#xff0c;市场处于混乱期。对于大多数供应商来讲&#xff0c;穿越新周期的战略一定是先有规模&#xff08;市场份额&#xff09;&#xff0c;然后才是利润。 在6月8日召开的2023&#xff08;第十四届&#xff09;高工智能汽车开发者大…

8个你必须知道的Java8新特性,让你的代码变得优雅!

Java 8 是一次重大的发行版更新&#xff0c;引入了大量新特性和改进&#xff0c;以下是 Java 8 的主要特性&#xff1a; 文章目录 Java 8 是一次重大的发行版更新&#xff0c;引入了大量新特性和改进&#xff0c;以下是 Java 8 的主要特性&#xff1a;1.Lambda 表达式2.Stream …

云平台 stm32连接阿里云2023最新版本保姆级别教学只看这一篇就够了~

注册账号 阿里云平台点击直达 点击控制台 鼠标悬浮会出现下拉栏 点击物联网 再点击物联网平台 点击公共实例 新用户需要开通 开通需要五分钟的时间 点击创建产品 蓝色显眼字体 参数设置 仔细比对下图 点击查看产品详情 蓝色显眼字体 点击功能定义 点击编辑草图 实际上就是定义…

如何通过Android平台的API实现5G网络的支持 安卓系统版本和5g网络相关【一】

前面分享了两篇5G基带相关的移植修改博文。 安卓高通机型的基带移植 修改 编译的相关 增加信号 支持5G等【一】 安卓高通机型的基带移植 修改 编译的相关 增加信号 支持5G等【二】 今天的帖子聊聊安卓版本与5G网络与机型和修改之间相关的话题。众所周知&#xff0c;目前的机型…

如何获取签章定位信息

在合同系统中&#xff0c;经常需要在合同文档的特定位置放置签名/印章图片。在合同拟稿过程中&#xff0c;放置签名/印章图片只是为了获取一个精确的定位信息&#xff0c;在合同定稿阶段才根据拟稿阶段得到的位置信息&#xff0c;去插入真正的签名/印章。那么如何在合同系统中高…

基于OpenMV的疲劳驾驶检测系统的设计

一、前言 借助平台将毕业设计记录下来&#xff0c;方便以后查看以及与各位大佬朋友们交流学习。如有问题可以私信哦。 本文主要从两个方面介绍毕业设计&#xff1a;硬件&#xff0c;软件&#xff08;算法&#xff09;。以及对最后的实验结果进行分析。感兴趣的朋友们可以评论区…

创新案例|专注在线 协作平台 设计产品中国首家PLG独角兽企业蓝湖如何实现98%的头部企业渗透率

蓝湖起步于2015年&#xff0c;是一款服务于产品经理、设计师、工程师的产品设计研发在线协作工具&#xff0c; 2021年10月&#xff0c;蓝湖宣布完成C轮融资&#xff0c;融资额高达10亿人民币&#xff0c;称为中国2B市场中首家采用PLG发展的独角兽企业&#xff0c;并实现了从100…

conda虚拟环境列表错误module ‘attr‘ has no attribute ‘s‘的解决方法

列出虚拟环境列表命令&#xff1a;conda info -e 或者conda env listconda info -e 这个可以正常显示&#xff0c;conda env list却报错了&#xff0c;以前是没有问题的&#xff0c;因为这个命令我更习惯使用&#xff0c;所以这个小问题必须解决掉&#xff0c;或许其他读者可能…

undetected_chromedriver解决网页被检测

一、问题分析 selenium打开浏览器模仿人工操作是诸多爬虫工作者最万能的网页数据获取方式&#xff0c;但是在做自动化爬虫时&#xff0c;经常被检测到是selenium驱动。比如前段时间selenium打开维普高级搜索时得到的页面是空白页&#xff0c;懂车帝对selenium反爬也很厉害。 二…

【React】setState原理,SCU,不可变对象,Ref,受控组件,高阶组件,封装轮播图组件

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 setState原理setState异步更新 SCU不可变对象RefRef获取DOMRef获取组件 非受控组件受控组件高阶…

word目录怎么自动生成,3个步骤轻松搞定!

案例&#xff1a;我在做策划案的时候&#xff0c;需要制作目录。我觉得自己手动制作目录很困难&#xff0c;通过word的可以自动生成目录&#xff0c;但是我不知道具体的操作方法。有没有小伙伴可以分享一下&#xff1f; 在制作任务书、书写论文的时候&#xff0c;经常需要添加…

vue+java+springboot企业办公人事oa办公管理系统2142g

本企业OA管理系统有管理员和用户。管理员功能有个人中心&#xff0c;用户管理&#xff0c;公告信息管理&#xff0c;客户关系管理&#xff0c;通讯录管理&#xff0c;日程安排管理&#xff0c;车辆信息管理&#xff0c;文件信息管理&#xff0c;工作日志管理&#xff0c;上班考…

0基础学习VR全景平台篇第42篇:编辑器底部菜单-分组管理

大家好&#xff0c;欢迎观看蛙色VR官方系列——后台使用课程&#xff01; 本期为大家带来蛙色VR平台&#xff0c;底部菜单—分组管理功能操作。 功能位置示意 一、本功能将用在哪里&#xff1f; 分组管理&#xff0c;指观看者可点击不同分组&#xff0c;查看不同类型全景内容…

learn C++ NO.9——string(2)

引言&#xff1a; 现在是北京时间的2023年6月15日早上的10点14分。时间过得飞快&#xff0c;现在已经大一的最后一个星期了。明天也是大一最后一次课&#xff0c;线下的实训课。线下实训内容为c语言二级的内容&#xff0c;对我来说跟学校的课效率太低下了&#xff0c;我还是比…

初识网络之再看udp协议

目录 一、端口号 1. 五元组 2. 端口号范围划分 3. 一些知名端口号 4. 进程与端口号 5. 两个常用网络工具 5.1 netstat 5.2 pidof 二、UDP协议 1. udp协议格式 2. udp报文解包 3. udp报文分用 4. udp的特点 5. 缓冲区 5.1 tcp缓冲区 5.2 udp缓冲区 6. 一些常见…

函数重载异常的常见原因

函数重载异常的常见原因 使用重载函数时&#xff0c;如果数据类型不匹配&#xff0c;C尝试使用类型转换与形参进行匹配&#xff0c;如果转换后有多个函数能匹配上&#xff0c;编译将报错。引用可以作为函数重载的条件&#xff0c;但是&#xff0c;调用重载函数的时候&#xff0…

Linux:端口

端口是设备与外界进行通讯的出入口&#xff0c;端口可以分为物理端口和虚拟端口 物理端口&#xff1a;又叫接口&#xff0c;是可见的端口&#xff0c;比如HDMI端口、USB接口虚拟端口&#xff1a;是指计算机内部的端口&#xff0c;用来操作系统和外部进行交互使用 通过IP地址只能…

6.python高频函数-处理缺失值isnull()、fillna()、dropna()

前言 如何判断pandas.DataFrame、Series是否包含缺失值NaN以及如何处理缺失值NaN。 Part.1 isnull() 函数 使用 isnull()、isna() 确定每个元素的缺失值 如果值为 NaN&#xff0c;则值为 True&#xff0c;如果不是&#xff0c;则值为 False。 读取数据集 panel_data pd.r…