(K)MP有限状态自动机

模式匹配自动机

什么是有限状态自动机?
定义 n 个不同状态,记为 {1,2…n},在状态 i 时输入 s,达到状态 j,记为 goto (i,s)=j
对于字符串 s 而言,在一个状态 i 下输入一个字符 ch,也会达到一个指定状态 :
假定新的状态为串 s [1,i]+ch 的最长相等前后缀 ,便能够用这个状态机模拟 KMP 算法匹配字符串的过程。
当字符集仅为 a、b 时,有:


其中 goto (4,a)=3,也就是说 abab+a 的最长相等前后缀 对应的状态是状态 3 ,也即表示字符串 “aba” 的状态。
似乎这样就足够了。
我们获得了 goto 函数,定义为:

goto (Si,a):串 s [1,i] a 的最长相等前后缀。

为了得到这个 goto 函数的值,我们需要定义 fail 函数:

fail (Si): 串 s [1,i] 的最长相等前后缀。

因为得到 goto (i,a) 的前提是,知道 s [1,i] 的最长相等前后缀 s\[1,j] :若 s [j+1] 与 a 相同,则 goto (i,a)=j+1,否则求 s [1,j] 的最长相等前后缀,直到长度为 0。
为了表示 “s [j+1] 与 a 相同” 这一条件,定义函数:

follow (Si, a): 状态 Si 输入 a 后,来到下一个状态。

对于字符串 abcde,follow (0,a)=1,follow (1,b)=2,follow (2,c)=3… 以此类推,而其他值未定义。
到这里,goto 函数就可表示为:

state go_to(state s,char ch){while(follow(s,ch)未定义){s=fail[s];}return follow(s,ch);
}

若 s 为模式串的状态,ch 为 s 的后继字符,则这一 goto 值可当做新的 fail 值。

未定义状态,比如 follow (0,b), 计为 0 可不可行?
与之配套地,fail (0), 计为 0,也就是说空串的最长相等前后缀长度 为 0。
若 fail (0) 记为 - 1,则 follow (s==-1,ch) 将陷入故障状态:没有状态被记为 - 1。
问题出现了!函数不得不进入死循环:因为 s 一直为 0。
破环方式也很简单:

引入状态 - 1,未定义状态记为 - 1,fail (0)=-1,follow (-1, 任何字符)=0。

这样,当计算 ab+c 的最长相等前后缀 时,便能够得到 go_to (2,c)=0。
类似地,计算fail数组的函数为:

Compute_fail()
{fail(s0) = ⊥;s = s0;for( i =1 to |P| ){s = goto(s, P[i]);fail(si) = s ;}
}

goto 和 fail 数组的关系:fail 反映模式串中的某部分字符串的最长相等前后缀 ,goto 反映文本串和模式串的匹配情况。诚然,fail 数组可以通过 goto 函数得到,但记录一些中间状态有利于加速算法。

匹配函数:

Match(t)
{s= s0;for(int i=1 to |T|){if( s 是终止状态 )return 匹配!else  s=goto(s,T[i]);}
} 

MP 有限状态自动机

我们都知道 mp 的 c++ 写法。
基于以上定义,我们艰难地知道 mp 的有限状态自动机写法:

#include<bits/stdc++.h>
using namespace  std;
#define state int
string P; //模式串
string T;
state fail[1000005];
state edge[1000005][26];state follow(state s,char ch){if(s==-1) return 0;if(edge[s][ch-'A']==s+1) return s+1;return -1;
}
state go_to(state s,char ch){while(follow(s,ch)==-1){s=fail[s];}return follow(s,ch);
}void get_fail(){fail[0]=-1;state s_=0;for(int i=1;i<P.size();i++){s_=go_to(s_,P[i]);fail[state(i)]=s_;if(fail[s_]!=-1&&P[s_+1]-'A'==P[i+1]-'A'){fail[state(i)]=fail[s_];}//!!!K优化!!!edge[i-1][P[i] - 'A'] = i;}
}
void match(){state s_=0;for(int i=1;i<T.size();i++){s_=go_to(s_,T[i]);if(s_==state(P.size()-1)){cout<<i-P.size()+2<<endl;}}
}
signed main() {cin>>T>>P;P=" "+P;T=" "+T;get_fail();match();for(int i=1;i<P.size();i++){cout<<fail[i]<<" ";
}}

洛谷提交情况如下: 洛谷
这是一种没有任何实战意义的写法。
需要注意俩点:

if(edge[s][ch-‘A’]==s+1) return s+1;

只有计算 fail 函数时,遍历过某个字符时,才连一条 edge 边。
也就是说,在未遍历时,字符串 abc 的 follow (0,a)=-1,follow (1,b)=-1,follow (1,c)=-1, 而当遍历 b 时,follow (0,a)=1,follow (1,b)=2,follow (1,c)=-1。这样做的原因是,若模式串天然有 follow 边,则 fail 数组的值会依次为 - 1,1,2,3,4…

if(fail[s_]!=-1&&P[s_+1]-‘A’==P[i+1]-‘A’){
fail[state(i)]=fail[s_]; }

这是 knuth 优化。对于字符串 aaaa,mp 的 fail 数组是 0,1,2,3 而 kmp 的 fail 数组是 0,0,0,3。
因为 kmp 的 fail 数组不能很好地反映字符串的前后缀的关系,而我们通常需要利用这种关系,故现常用 mp,且把 mp 称为 kmp。

MP 算法是一个 O (m+n) 的算法,证明如下:

1. 在 check 函数中,对文本串扫描一遍,无回头扫描,消耗 O (n)
2. 自动机向右的移动距离 >= 向左移动的距离 >= 调用 fail 的次数,而向右的移动距离 = 对文本串扫描的距离 = n,故调用 fail 的次数 = O (n)
3. 构造 fail 数组时,向右的移动距离 = 对模式串扫描的距离 = m,即 Fail 构造复杂度的复杂度为 O (m)

综合为 O (m+n)。实际上,除了 aaab 匹配 aaaaaaaa 这种极端数据外,mp 和暴力算法复杂度接近:随机情况下,暴力的复杂度也接近 O (m+n),在数据随机生成的情况下,暴力匹配也基本很快就会失配。

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

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

相关文章

ssh连接慢的问题或zookeeper远程连接服务超时

问题原因&#xff1a; 在SSH登录过程中&#xff0c;服务器会通过反向DNS查找客户端的主机名&#xff0c;然后与登录的IP地址进行匹配&#xff0c;以验证登录的合法性。如果客户端的IP没有域名或DNS服务器响应缓慢&#xff0c;这可能导致SSH登录过慢。为了解决这个问题&#xf…

尤雨溪都打赏的虚拟列表组件,到底有多强

尤雨溪都打赏的虚拟列表组件&#xff0c;到底有多强&#xff1f; 在前端开发中&#xff0c;性能优化永远是绕不开的主题。今天就带你看看 vue-virtual-scroller&#xff0c;一款让你滚动页面时流畅得像火箭一样的 Vue 组件。本文将简单介绍这个组件的主要功能、技术特点&#x…

理解和检测横向运动

希望对组织发起勒索软件攻击的威胁行为者能够使用被盗的凭据进入用户的电子邮件帐户。利用鱼叉式网络钓鱼技术和侦察&#xff0c;威胁行为者向 IT 部门发送电子邮件&#xff0c;要求提供重要网络应用程序的凭据。他们获得凭据&#xff0c;深入网络&#xff0c;并开始发起勒索软…

JavaWeb合集07-MyBatis

七、MyBatis MyBatis是一款优秀的持久层&#xff08;dao&#xff09;框架&#xff0c;用于简化JDBC的开发。 MyBatis本是Apache的一个开源项目iBatis, 2010年这个项目由apache迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。 官网&#xff1a;https://mybati…

Axure重要元件三——中继器查询和统计

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 本节课&#xff1a;中继器查询页数 课程内容&#xff1a;查询中继器页面、自动统计页数、自动统计数据条数、上一页下一页 应用场景&#xff1a;表单的查询、表单的基本…

10秒钟用Midjourney画出国风味的变形金刚

上魔咒 Optimus Prime comes from the movie Transformers, Chinese style, Wu ShanMing, Ink Painting Halo Dyeing, Conceptual of the Digita Art, MasterComposition, Romantic Ancient Style, Inspired by traditional patterns and symbols, Minimalism, do not con…

【数据分享】全国资源和环境-环境污染治理投资(1998-2021年)

数据介绍 一级标题指标名称单位指标解释资源和环境环境污染治理投资总额亿元环境污染治理投资指在污染源治理和城市环境基础设施建设的资金投入中&#xff0c;用于形成固定资产的资金&#xff0c;其中污染源治理投资包括工业污染源治理投资和“三同时”项目环保投资两部分。环…

ssm基于SSM的社区管理系统+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 [2 系统…

1.2024.10.17

2024.10.17 总体规划 总体规划 写这个合集的原因 记录自己入行之前成长过程。本人菜鸟一枚&#xff0c;大佬不喜勿喷。 目前的规划 更新频率 尽量一天一更&#xff0c;会更新之前发布的笔记&#xff0c;争取笔记更加完善。 学习方法 目标 通过面试&#xff0c;成功入行嵌…

Tailwind css系列教程(三)

vue3环境搭建Tailwind CSS 1、创建vue3项目 创建项目&#xff1a;npm create vitelatest vue3app01 --template vue 进入项目文件夹&#xff1a;cd vue3app01 加载默认库&#xff1a;npm install 测试运行&#xff1a;npm run dev 2、搭建tailwind css &#xff08;1&a…

Ionic 对话框

Ionic 对话框 Ionic 是一个强大的开源框架&#xff0c;用于构建高性能、高质量的移动和桌面应用程序。它基于流行的 Web 技术如 HTML、CSS 和 JavaScript&#xff0c;并且与 Angular、React 和 Vue 等前端框架紧密集成。Ionic 提供了一套丰富的组件&#xff0c;其中包括对话框…

C++面试速通宝典——27

504. 孤儿进程和僵尸进程是什么&#xff1f;怎么处理&#xff1f; 孤儿进程&#xff1a;当一个父进程结束&#xff0c;而他的一个或多个子进程还在运行时&#xff0c;那些子进程将成为孤儿进程。孤儿进程会被init进程&#xff08;进程ID为1&#xff09;自动领养&#xff0c;in…

2010年国赛高教杯数学建模C题输油管的布置解题全过程文档及程序

2010年国赛高教杯数学建模 C题 输油管的布置 某油田计划在铁路线一侧建造两家炼油厂&#xff0c;同时在铁路线上增建一个车站&#xff0c;用来运送成品油。由于这种模式具有一定的普遍性&#xff0c;油田设计院希望建立管线建设费用最省的一般数学模型与方法。   1. 针对两炼…

在线考试系统的现代化解决方案:Spring Boot与JavaWeb

3系统分析 3.1可行性分析 通过对本基于JavaWeb技术的在线考试系统设计与实现实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本基于JavaWeb技术的在线考试系统设…

10 排序算法:冒泡排序与快速排序(算法原理、算法实现、时间和空间复杂度分析)

目录 1 十大常见的排序算法 1.1 算法的稳定性 2 冒泡排序 2.1 算法原理 2.2 算法实现 2.3 时间空间复杂度分析 2.3.1 时间复杂度分析 2.3.2 空间复杂度分析 3 快速排序 3.1 算法原理 3.1.1 排序思想 3.1.2 递归过程 3.2 示例 3.2.1 示例 1 3.2.2 示例 2 3.2.3 …

设计一个支持自动化测试执行的测试框架

设计一个支持自动化测试执行的测试框架 在现代软件开发中,自动化测试是确保软件质量的重要手段。一个良好的测试框架不仅可以提高测试效率,还能帮助开发团队快速发现和修复缺陷。本文将介绍如何设计一个支持自动化测试执行的测试框架,涵盖框架的基本结构、核心功能以及实现…

JAVA 中系统相关的类

System 类 代表的是当前 Java 程序运行的平台&#xff08;操作系统&#xff09;&#xff0c;该类被关键字 final 修饰&#xff0c;即该类不能够派生子类&#xff0c;同时该类的构造器被关键字 private 修饰&#xff0c;因此不能够创建 System 类型的实例对象。 System 类中定…

【数据采集工具】Sqoop从入门到面试学习总结

国科大学习生活&#xff08;期末复习资料、课程大作业解析、大厂实习经验心得等&#xff09;: 文章专栏&#xff08;点击跳转&#xff09; 大数据开发学习文档&#xff08;分布式文件系统的实现&#xff0c;大数据生态圈学习文档等&#xff09;: 文章专栏&#xff08;点击跳转&…

【DNF mysql8.0安装】DNF安装MySQL服务器教程

在基于Red Hat的Linux发行版中&#xff0c;如CentOS或Fedora&#xff0c;DNF&#xff08;Dandified Yum&#xff09;是包管理器&#xff0c;用于安装、更新和卸载软件包。以下是使用DNF安装MySQL服务器&#xff08;也称为MySQL Community Server&#xff09;的步骤&#xff1a;…

网易博客旧文----Xtreme ToolkitPro 的CommandBarsDesigner编辑生成的界面如何使用

Xtreme ToolkitPro 的CommandBarsDesigner编辑生成的界面如何使用 2013-03-04 17:22:42| 分类&#xff1a; MFC | 标签&#xff1a; |举报 |字号大中小 订阅 著名的界面开发商Codejock Software开发的MFC界面控件和BCGsoft公司开发的BCGControlBarPro界面有得一拼。 codejock…