KMP算法和Manacher算法

KMP算法

KMP算法解决的问题

KMP算法用来解决字符串匹配问题: 找到长串中短串出现的位置.

KMP算法思路

暴力比较与KMP的区别
  • 暴力匹配: 对长串的每个位,都从头开始匹配短串的所有位.
    image
  • KMP算法: 将短字符串前后相同的部分存储在 n e x t next next数组里,让之前匹配过的信息指导之后的匹配.
    image
n e x t next next数组及其求法

n e x t next next数组体现字符串某位前边子串最长匹配前缀和最长匹配后缀的匹配长度(可以有交叉). n e x t [ i ] next[i] next[i]表示第 i i i位前边的最长匹配后缀对应的最长匹配前缀的后一位.
下面是一个next数组的例子:
image

next数组的求法

n e x t next next数组的求法用到了递推思想:

  1. 0 0 0位前边没有匹配前后缀,因此 n e x t [ 0 ] = − 1 next[0]=-1 next[0]=1

  2. 1 1 1位前缀字符串的长度为1,因此 n e x t [ 1 ] = 0 next[1]=0 next[1]=0

  3. 站在第 p o s pos pos位上,就要考虑以第 i − 1 i-1 i1位结尾的最长匹配(也就是不断地求 n u m s [ p o s − 1 ] nums[pos-1] nums[pos1] n e x t [ n e x t [ . . . n e x t [ p o s − 1 ] ] ] next[next[...next[pos-1]]] next[next[...next[pos1]]]之间的关系):

image

  • c n cn cn指针指向前一个匹配后缀的下一位,即 c n = n e x t [ p o s − 1 ] cn=next[pos-1] cn=next[pos1]
  • 若前一个匹配后缀的下一位字符刚好与待匹配字符相同,即 m s [ c n ] = = m s [ p o s − 1 ] ms[cn]==ms[pos-1] ms[cn]==ms[pos1],则更新next数组,将 n e x t [ p o s ] next[pos] next[pos]指向 c n cn cn的下一位 n e x t [ p o s ] = c n + 1 next[pos]=cn+1 next[pos]=cn+1
  • 若前一个匹配后缀的下一位字符与待匹配字符不同,即 m s [ c n ] ! = m s [ p o s − 1 ] ms[cn]!=ms[pos-1] ms[cn]!=ms[pos1],则应该找前一个匹配数组,即 c n = n e x t [ c n ] cn=next[cn] cn=next[cn]
  • 若最终找到 c n = = − 1 cn==-1 cn==1也没找到,则 p o s − 1 pos-1 pos1位实在没有匹配后缀了,将其 n e x t next next数组置 0 0 0,即 n e x t [ p o s ] = 0 next[pos]=0 next[pos]=0
// 计算ms字符串的next[]数组
public static int[] getNextArray(char[] ms) {
	if (ms.length == 1) {
		return new int[] { -1 };
	}
	int[] next = new int[ms.length];
	next[0] = -1;	// 第0位前边没有前缀字符串,因此返回-1
	next[1] = 0;	// 第1位前缀字符串的长度为1,若该位匹配不上则只能去匹配首位,因此返回0

	// 从第2位开始,递推出后面位的next[]值
	for (int pos = 2; pos < ms.length; pos++) {
		// 一直向前找前边位的匹配前缀且该前缀的后一位与本位相同
		int cn = next[pos - 1];
		while (cn != -1 && ms[cn] != ms[pos-1]) {
			// 将前缀的后一位与当前位的前一位进行对比
			cn = next[cn];
		}

		// 判断是否能找到匹配前缀
		//if (cn != -1) {
		//	// 若能找到匹配前后缀,则返回匹配前缀的后一位
		//	next[pos] = cn + 1;
		//} else {
		//	// 若找不到匹配前后缀,返回-1
		//	next[pos] = 0;
		//}
		// 上述判断语句可以简化为一句
		next[pos] = cn + 1;
	}
	return next;
}

在写入 n e x t next next数组的 p o s pos pos位时要注意: 匹配前缀延伸的时候,要判断的是 m s [ c n ] 与 m s [ p o s − 1 ] ms[cn]与ms[pos-1] ms[cn]ms[pos1]之间是否相等
(因为 n e x t next next数组保存的是本位前一位的匹配前缀的下一位,因此 m s [ c n ] ms[cn] ms[cn]指向匹配前缀的下一位, m s [ p o s − 1 ] ms[pos-1] ms[pos1]指向上次计算未进行匹配的位)

题目代码
P3375 【模板】KMP
#include <bits/stdc++.h>
using namespace std;
int kmp[1000005];
int la,lb,j;
char a[1000005],b[1000005];
int main() {
	cin>>a+1;
	cin>>b+1;
	la=strlen(a+1);
	lb=strlen(b+1);
	for (int i=2; i<=lb; i++) {
		while(j&&b[i]!=b[j+1])
			j=kmp[j];
		if(b[j+1]==b[i])j++;
		kmp[i]=j;
	}
	j=0;
	for(int i=1; i<=la; i++) {
		while(j>0&&b[j+1]!=a[i])
			j=kmp[j];
		if (b[j+1]==a[i])
			j++;
		if (j==lb) {
			cout<<i-lb+1<<endl;
			j=kmp[j];
		}
	}
	for (int i=1; i<=lb; i++)
		cout<<kmp[i]<<" ";
	return 0;
}

Manacher算法

Manacher算法解决的问题

Manacher算法用来寻找字符串的最长回文子串.

回文串的相关概念

  1. 回文右边界: 当前所有回文串中,回文右边界所能到达的最右位置.
  2. 回文右边界中心: 以回文右边界结尾的最长回文串的回文中心.

Manacher算法思路

从第一位开始,遍历字符串的所有位.初始时回文右边界为-1.
image
当遍历到第pos位时,有以下两种情况

  1. p o s pos pos不在回文右边界 r i g h t B o r d e r rightBorder rightBorder以内 ( p o s > r i g h t B o r d e r ) (pos > rightBorder) (pos>rightBorder): 以该位为中心向两边暴力扩展回文串.
  2. p o s pos pos在回文右边界 r i g h t B o r d e r rightBorder rightBorder以内 ( p o s < = r i g h t B o r d e r ) : (pos <= rightBorder): (pos<=rightBorder):找到回文右边界中心 r i g h t C e n t e r rightCenter rightCenter,对应的回文左边界,以及 p o s pos pos关于回文右边界中心的对称点 p o s ′ pos' pos.这样 p o s ′ pos' pos的回文半径可以用来指导 p o s pos pos的回文半径
    1. p o s ′ pos' pos回文串关于 r i g h t C e n t e r rightCenter rightCenter的对称串在回文右边界以内 ( p o s + c u r R a d i u s [ p o s ] − 1 < = r i g h t B o r d e r ) (pos + curRadius[pos] -1 <= rightBorder) (pos+curRadius[pos]1<=rightBorder),说明 p o s pos pos的回文半径与 p o s ′ pos' pos的回文半径相同
    2. p o s ′ pos' pos回文串关于 r i g h t C e n t e r rightCenter rightCenter的对称串在回文右边界以外 ( p o s + c u r R a d i u s [ p o s ] − 1 > r i g h t B o r d e r ) (pos + curRadius[pos] -1 > rightBorder) (pos+curRadius[pos]1>rightBorder),由对称性可知,对称串超出回文右边界的部分一定不能构成以 p o s pos pos为中心的回文.因此 p o s pos pos的回文半径即为 p o s pos pos到回文右边界之间.
      在遍历过程中维护的回文右边界串并不一定是最长回文子串,如上面演示图中第一种情况为例: 遍历结束时,回文右边界串为" a b c b a abcba abcba",最长回文子串为" a b c b a d a b c b a abcbadabcba abcbadabcba"

题目代码

P3805 【模板】manacher
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=22000010;
char fr[maxn],s[maxn];
ll len[maxn];
int main()
{
	scanf("%s",fr);
	ll frlen=strlen(fr),count1=0;
	s[count1++]='*';
	for(ll i=0;i<frlen;i++)
	{
		s[count1++]='#';
		s[count1++]=fr[i];
	}
	s[count1++]='#';
	s[count1++]='!';
	len[0]=0;
	ll mx=0,ans=0,id=0;
	for(ll i=1;i<count1;i++)
	{
		if(i<mx)
			len[i]=min(mx-i,len[2*id-i]);
		else
			len[i]=1;
		while(s[i-len[i]]==s[i+len[i]])
			len[i]++;
		if(len[i]+i>mx)
		{
			mx=len[i]+i;
			id=i;
			ans=max(ans,len[i]-1);
		}
	}
	printf("%lld",ans);
	return 0;
}

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

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

相关文章

如何利用pynlpir进行中文分词并保留段落信息

一、引言 nlpir是由张华平博士开发的中文自然处理工具&#xff0c;可以对中文文本进行分词、聚类分析等&#xff0c;它既有在线的中文数据大数据语义智能分析平台&#xff0c;也有相关的python包pynlpir&#xff0c;其github的地址是&#xff1a; Pynlpir在Github上的地址 这…

算法(6)——模拟

一、什么是模拟 模拟是对真实事物或者过程的虚拟。在编程时为了实现某个功能&#xff0c;可以用语言来模拟那个功能&#xff0c;模拟成功也就相应地表示编程成功。 二、模拟算法的思路 模拟算法是一种基本的算法思想&#xff0c;可用于考查程序员的基本编程能力&#xff0c;…

抖店入驻费用是多少?新手入驻都有哪些要求?2024费用明细!

我是电商珠珠 我做电商做了将近五年&#xff0c;做抖店做了三年多&#xff0c;期间还带着学员一起做店。 今天&#xff0c;就来给大家详细的讲一下在抖音开店&#xff0c;需要多少费用&#xff0c;最低需要投入多少。 1、营业执照200元左右 就拿个体店举例&#xff0c;在入…

二叉搜索树题目:将有序数组转换为二叉搜索树

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法证明代码复杂度分析 题目 标题和出处 标题&#xff1a;将有序数组转换为二叉搜索树 出处&#xff1a;108. 将有序数组转换为二叉搜索树 难度 4 级 题目描述 要求 给定整数数组 nums \texttt{nums}…

大辩论:人工智能时代人类和软件的未来

关于人工智能将在多大程度上接管软件开发、交付和支持任务及其对就业的影响&#xff0c;聆听双方的争论&#xff0c;对于技术来说既令人兴奋&#xff0c;又让人类感到恐惧。争论是这样的&#xff1a; 人工智能倡导者&#xff1a;欢迎来到未来&#xff01;凭借当今人工智能的能…

猫挑食不吃猫粮怎么办?可以解决猫咪挑食的主食冻干推荐

现在的猫奴们普遍将自家的小猫视为掌上明珠&#xff0c;宠爱有加。然而&#xff0c;这种宠爱有时也会导致猫咪养成一些不良习惯&#xff0c;比如挑食。猫挑食不吃猫粮怎么办&#xff1f;今天为大家分享一个既不让咱宝贝猫咪受罪又可以改善猫咪挑食的方法。 一、猫咪是为什么挑食…

(C语言)qsort函数详解

目录 1. qsort解释 2. qsort实例 2.1 qsort排列整形数组类型&#xff1a; 2.2 qsort排列结构体类型数据&#xff08;字符串&#xff09;&#xff1a; 2.3 qsort排列结构体类型数据&#xff08;整形&#xff09;&#xff1a; 1. qsort解释 我们可以进入网站&#xff1a;qso…

第一天 走进Docker的世界

第一天 走进Docker的世界 介绍docker的前世今生&#xff0c;了解docker的实现原理&#xff0c;以Django项目为例&#xff0c;带大家如何编写最佳的Dockerfile构建镜像。通过本章的学习&#xff0c;大家会知道docker的概念及基本操作&#xff0c;并学会构建自己的业务镜像&…

王者荣耀整蛊搭建直播新玩法/obs贴纸配置教程

最近很火的王者荣耀整蛊直播&#xff0c;相信很多玩王者的玩家也想开一个直播&#xff0c;但是看到这种直播娱乐效果很有意思也想搭建一个&#xff0c;这里梦哥给大家出了一期搭建的教程&#xff01; 进阶版视频教程&#xff1a; 这期的教程是进阶版新玩法升级&#xff0c;具体…

DataGrip 2023:让数据库开发变得更简单、更高效 mac/win

JetBrains DataGrip 2023是一款功能强大的数据库IDE&#xff0c;专为数据库开发和管理而设计。通过DataGrip&#xff0c;您可以连接到各种关系型数据库管理系统(RDBMS)&#xff0c;并使用其提供的一组工具来查询、管理、编辑和开发数据库。 DataGrip 2023软件获取 DataGrip 2…

前端面试 跨域理解

2 实现 2-1 JSONP 实现 2-2 nginx 配置 2-2 vue 开发中 webpack自带跨域 2 -3 下载CORS 插件 或 chrome浏览器配置跨域 2-4 通过iframe 如&#xff1a;aaa.com 中读取bbb.com的localStorage 1)在aaa.com的页面中&#xff0c;在页面中嵌入一个src为bbb.com的iframe&#x…

大模型理论基础(so-large-lm)课程笔记!

Datawhale干货 作者&#xff1a;辣条&#xff0c;Datawhale优秀学习者 前 言 在当前信息时代&#xff0c;大型语言模型&#xff08;Large Language Models&#xff0c;LLMs&#xff09;的发展速度和影响力日益显著。随着技术进步&#xff0c;我们见证了从基本的Transformer架构…

【三维重建】【SLAM】SplaTAM:基于3D高斯的密集RGB-D SLAM(CVPR 2024)

题目&#xff1a;SplaTAM: Splat, Track & Map 3D Gaussians for Dense RGB-D SLAM 地址&#xff1a;spla-tam.github.io 机构&#xff1a;CMU&#xff08;卡内基梅隆大学&#xff09;、MIT&#xff08;美国麻省理工&#xff09; 总结&#xff1a;SplaTAM&#xff0c;一个新…

在你的 Vue + Electron 项目里,引入 ESLint

因为我的项目是基于 Electron 平台的 Web 应用&#xff0c;使用 Vue 3 实现&#xff0c;而且用了 TypeScript&#xff0c;所以&#xff0c;在引入 ESLint 的时候&#xff0c;要考虑好几种规范的问题。 文章目录 零、简介1. 规则2. 配置文件3. 共享配置4. 插件5. 解析器6. 自定义…

【比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据】操作批量新增、分页查询(三)

orm框架使用性能比较 比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据 环境&#xff1a; idea jdk17 spring boot 3.0.7 mysql 8.0测试条件常规对象 orm 框架是否支持xml是否支持 Lambda对比版本mybatis☑️☑️3.5.4sqltoy☑️☑️5.2.98lazy✖️☑️1.2.4…

哪个有名的工具可以安全记事 私密记事本笔记推荐

在这个数字化的时代&#xff0c;我们的生活已经离不开各种记事工具。它们帮助我们记录生活中的点点滴滴&#xff0c;无论是工作上的重要事项&#xff0c;还是个人的私密心情。然而&#xff0c;当我在寻找一个能够安心记录私密事情的工具时&#xff0c;安全性成为了我最关心的因…

23.基于springboot + vue实现的前后端分离-在线旅游网站系统(项目 + 论文PPT)

项目介绍 本旅游网站系统采用的数据库是MYSQL &#xff0c;使用 JSP 技术开发&#xff0c;在设计过程中&#xff0c;充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。 技术选型 后端: SpringBoot Mybatis 数据库 : MyS…

Matlab 机器人工具箱 动力学

文章目录 R.dynR.fdynR.accelR.rneR.gravloadR.inertiaR.coriolisR.payload参考链接 官网&#xff1a;Robotics Toolbox - Peter Corke R.dyn 查看动力学参数 mdl_puma560; p560.dyn;%查看puma560机械臂所有连杆的动力学参数 p560.dyn(2);%查看puma560机械臂第二连杆的动力学…

MongoDB Java实战

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于MongoDB系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础…

SpringBoot+Vue实现el-table表头筛选排序(附源码)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;在笑大学牲 &#x1f39f;️个人主页&#xff1a;无所谓^_^ ps&#xff1a;点赞是免费的&#xff0c;却可以让写博客的作者开心好几天&#x1f60e; 前言 后台系统对table组件的需求是最常见的&#xff0c;不过element-ui的el…