manacher算法

这篇具有很好参考价值的文章主要介绍了manacher算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

初始化?

给定一个字符串,求其最长回文串,比如:

aababa,最长回文长度为 3,是ababa;

abbabb,最长回文长度为 2,是abba;

以上两个回文串有奇回文和偶回文,这样处理比较繁琐,需要我们进行分类讨论。

所以我们第一步就是先将字符串统一处理为奇回文。

也就是将每两个字符串之间插入一个占位符(随便吧,我用的是 #),强制将所有的都改为奇回文串,然后再在前面和后面各加入一个不同的字符,防止越界。

e.g.我们可以将aababa变换为@#a#a#b#a#b#a#%

Code

int p=0;
s[p]='@';s[++p]='#';
for(int i=1;i<=n;++i){
    s[++p]=t[i];
    s[++p]='#';
}
s[p+1]='%';

实现?

对于正常的暴力,大概是 \(O(n^3)\) 的,不过你优化一下,你大概可以优化到 \(O(n^2)\)

那么暴力就有一个致命的缺陷:每次求完一个回文串后,什么信息都不能继承,导致需要重新算一遍,这就很费时间好吧,则我们需要考虑一下,之前已经求出来的信息,能不能用在这次呢?

显然是可以的。

我们可以定义一个数组 \(p\)\(p_i\) 表示 \(i\) 所在的字符为中心的最长回文的半径。

且可以发现一个性质,就是我们插入那些占位符的 \(p_i\) 是奇数,而原串中的字符的 \(p_i\) 都是偶数。(似乎没什么用)

并且我们记录一个 \(mid\),表示在i之前所有的回文中心中,回文右端点最远在哪,记 \(mx\) 表示这个最远的右端点所对应的回文中心

接下来,我们考虑如何用这个东西维护 \(p_i\)

这是需要分类讨论的,即:

  • \(mid<i<mx\) 时,情况如下图:
    manacher算法

我们可以在 \(mid\) 的另一边找到 \(i\) 的一个对称点 \(j\),那么 \([i-p_j,i+p_j]=[j-p_j,j+p_j]\)。但是要注意一下边界情况,回文的长度应该不超过 \(mid\times 2-mx\)(\(mx-i\) 也是一样的),毕竟超过了就不能保证它相等了。

所以对于这种情况,我们可以将 \(p_i\) 的初值设为:\(min(p_{mid\times 2-i},mx-i)\)。然后暴力拓展即可。

  • \(i>mx\) 时:

我们找不到对称点,只能暴力拓展。

最后考虑如何更新 \(mid\)\(mx\)

我们需要能继承的越多,那尽量要多些第一种情况,那么当我们遇到某个右端点比 \(mx\) 大的时候,就可以更新了。

\(mid\to i,mx\to i+p_i\) 即可。文章来源地址https://www.toymoban.com/news/detail-710461.html

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=22000005;
inline int read(){
	int x=0,f=1;
	char ch;
	ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-f;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+(ch-'0');
		ch=getchar();
	}
	return x*f;
}
int n;
char s[N],t[N];
int p[N];
void manacher(){
	s[0]='@';
	int q=0;
	s[++q]='#';
	for(int i=0;i<n;++i){
		s[++q]=t[i];
		s[++q]='#';
	}
	s[q+1]='%';//初始化
	int mx=0,mid=0;
	for(int i=1;i<=q;i++){
		if(i<mx) p[i]=min(p[mid*2-i],mx-i);//继承
		while(s[i+p[i]+1]==s[i-p[i]-1]) ++p[i];//暴力拓展
		if(p[i]+i>mx) mx=i+p[i],mid=i;//更新
		
	}
}
signed main(){
	cin>>t;
	n=strlen(t);
	manacher();
	int ans=0; 
	for(int i=1;i<=2*n+1;++i)
		ans=max(ans,p[i]);
	cout<<ans;
	return 0;
}

到了这里,关于manacher算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言基础考研向】10 字符数组初始化及传递和scanf 读取字符串

    字符数组的定义方法与前面介绍的一维数组类似.例如, 字符数组的初始化可以采用以下方式. (1)对每个字符单独赋值进行初始化.例如, (2)对整个数组进行初始化.例如, 但工作中一般不用以上两种初始化方式,因为字符数组一般用来存取字符串.通常采用的初始化方式是

    2024年01月25日
    浏览(45)
  • react学习(一)之初始化一个react项目

    React 是一个用于构建用户界面(UI)的 JavaScript 库,用户界面由按钮、文本和图像等小单元内容构建而成。React 帮助你把它们组合成可重用、可嵌套的 组件 。从 web 端网站到移动端应用,屏幕上的所有内容都可以被分解成组件,即,可由react构建。 A JAVASCRIPT LIBRARY FOR BUILDING

    2024年04月26日
    浏览(28)
  • LLMs之Colossal-LLaMA-2:源码解读(train.py文件)基于给定数据集实现持续预训练LLaMA-2—解析命令行参数→初始化配置(分布式训练环境colossalai+训练日志+加速插

    LLMs之Colossal-LLaMA-2:源码解读(train.py文件)基于给定数据集实现持续预训练LLaMA-2—解析命令行参数→初始化配置(分布式训练环境colossalai+训练日志+加速插件)→数据预处理(初始化分词器+数据处理器+数据加载器)→模型训练(初始化模型/优化器/学习率调度器/梯度检查点/Flash-Att

    2024年02月06日
    浏览(30)
  • 初始化一个Gin框架的Go-Web项目

    使用到的第三方库 gin Gin 框架 viper 配置文件管理 cors 跨域资源请求配置 gorm ORM 库 zap 日志记录 Go 语言程序的入口点 main.go 文件 使用 flag 读取配置文件路径参数,默认当前目录下 使用 viper 读取 config.ini 配置文件初始化初始数据 初始化随机数种子 初始化数据库 声明启动程序

    2024年02月09日
    浏览(43)
  • 武林新秀(一)`git init` 初始化一个新的Git仓库

    git init 是 Git 版本控制系统中用于初始化一个新的 Git 仓库或重新初始化一个现有的仓库的命令。“init” 是 “initialize”(初始化)的缩写。执行此命令后,会创建一个名为 .git 的子目录,其中包含所有的仓库元数据,这使得目录成为一个 Git 仓库。 基本语法: --bare : 创建一

    2024年02月10日
    浏览(46)
  • 数据结构与算法——顺序表(顺序存储结构)及初始化详解

    顺序表 ,全名 顺序存储结构 ,是线性表的一种。通过《什么是线性表》一节的学习我们知道,线性表用于存储逻辑关系为“一对一”的数据,顺序表自然也不例外。 不仅如此,顺序表对数据的物理存储结构也有要求。 顺序表存储数据时,会提前申请一整块足够大小的物理

    2024年02月16日
    浏览(31)
  • MATLAB初始化智能算法编码-产生随机不重复整数序列矩阵

    产生随机不重复整数序列矩阵是智能算法最常用的操作之一,以下给出具体方法: clc;close all;clear all;warning off;%清除变量 rand(\\\'seed\\\', 100); randn(\\\'seed\\\', 100); format long g; N=10; % 设定优化问题维数 lb=0*ones(1,N);% 自变量上限 ub=1*ones(1,N);% 自变量下限 popsize=10;% 种群数 Chrom=mygenfun(popsize,N,lb,u

    2024年01月24日
    浏览(33)
  • 分享用 vector的vector实现一个二维数组并初始化的逆置矩阵问题

    目录 题目名称 867.转置矩阵 1.题目 2.题目分析 3.题目知识点 3.1vector的构造函数 3.2vector构造二维数组 最后💐 推荐阅读顺序: 1.题目-2.题目分析-3.题目知识点 如果矩阵 matrix为 m 行 n列,则转置后的矩阵 matrixT为 n行 m列,且对任意 0≤im和 0≤jn,都有 matrixT[j][i]=matrix[i][j] 创建一个

    2024年01月17日
    浏览(46)
  • ORB-SLAM2算法12之单目初始化Initializer

    ORB-SLAM2算法7详细了解了 System 主类和多线程、

    2024年02月10日
    浏览(35)
  • 用React给XXL-JOB开发一个新皮肤(二):目录规划和路由初始化

    一. 简述 二. 目录规划 三. Vite 配置 3.1. 配置路径别名 3.2. 配置 less 四. 页面 4.1. 入口文件 4.2. 骨架文件 4.3. 普通页面 五. 路由配置 六. 预览启动 上一篇文章我们介绍了项目初始化,此篇文章我们会先介绍下当前项目的目录规划,接着对 vite 配置以便我们后续的开发,最后会根

    2024年01月20日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包