首页 > 其他分享 >浅谈 Manacher

浅谈 Manacher

时间:2024-10-21 14:46:14浏览次数:1  
标签:le 浅谈 int Manacher mid 回文 rightarrow

从某种方面来说,Manacher 算法是朴素 \(O(n^2)\) 暴力算法的优化。。。

那就得先了解一下 Manacher 的朴素算法------

朴素算法

枚举中心点并不断向外展开(例如:\([i,i]\rightarrow [i+1,i+1]\rightarrow [i+2,i+2]\rightarrow \dots\))

缺点:

  1. 时间复杂度:\(O(n^2)\),慢
  2. 不能处理长度为偶数的回文串,菜

Manacher

想要优化,首先得解决几个问题:

如何处理长度为偶数的回文串?

可以这样:在每个字符串间及开头结尾加上一个特殊字符(例子:aaaa $\rightarrow $ ~#a#a#a#a#

考虑例子中为什么开头第一个地方有个 ~

这个后面代码中再说(防止数组越界)。。。

如何使时间复杂度降到线性?

记录一个数组p[i]表示以 \(i\) 为回文中心的回文半径。

现在就是处理来到 \(i\) 这个点,如何转移p[i]

我们在这里维护一个当前回文串最右端点 \(r\),和其对称中心 \(mid\)。

当 \(i\le r\) 时

因为 \(i+p[i]-1\le r\)

所以 \(p[i]\le r-i+1\)

我们通过以 \(mid\) 为对称轴得到一个与当前的 \(i\) 对称的点 \(j\)(这个对称点点的p[]已经处理出来)来转移p[i],同时还能向外扩展:while(s[i-p[i]]==s[i+p[i]])++p[i];

求 \(j\) 就用初一的中点公式:\(\frac{i+j}{2}=mid\rightarrow j=2*mid-i\)

所以 \(p[i]=min(p[2*mid-i],r-i+1)\) 。

当 \(i>r\) 时

\(p[i]=1\),就是不能向外扩展(只有自己本身的长度)。

板子代码:

#include <bits/stdc++.h>
using namespace std;
const int N=3e7+5;
int n,p[N];
char s[N],st[N];
int cnt=1; 
void init()
{
	s[0]='~';
	s[cnt++]='#';
	for(int i=0;i<n;i++)
	{
		s[cnt++]=st[i];
		s[cnt++]='#';
	}
}
int main()
{
	cin>>st;
	n=strlen(st);
	init();
	int ans=-1;
	for(int i=1,r=0,mid=0;i<=cnt;i++)
	{
		if(i<=r)p[i]=min(p[2*mid-i],r-i+1);
		while(s[i-p[i]]==s[i+p[i]])++p[i];//解释一下:s的第一位那个~,就是在while循环中防止越界
		if(i+p[i]>r)r=p[i]+i-1,mid=i;
		if(ans<p[i])ans=p[i];
	}
	cout<<ans-1;
	return 0;
}

标签:le,浅谈,int,Manacher,mid,回文,rightarrow
From: https://www.cnblogs.com/tyccyt/p/18489455

相关文章

  • 浅谈红队攻防之道-Cobalt Strike实战
    我不想一辈子被人踩在脚下,你以为我是臭要饭的,我努力了三年,就是要等一个机会,我要争一口气,不是想证明我了不起;我是要告诉人家,我失去的东西一定要拿回来!成果cs获取shellmsf已经拿到了meterpreter现在把这个meterpreter的shell派生到CS上面,也就是让CS也也拿到一个shellms......
  • 浅谈 tarjan
    就是记录两个数组:dfn[]和low[]其中dfn[]表示访问的顺序,low[u]用来存储\(u\)不经过其父亲能到达的最小时间戳。。。搬一下wiki的图。。。我们发现\(low[v]\gedfn[u]\)可以表示不能回到祖先,则\(u\)点位割点。。。直接上代码P3388------>#include<bits/stdc++.h>usi......
  • 浅谈一类最短路问题
    P2685[TJOI2012]桥首先求出一个最短路树,显然只能删除树上的边才对答案有影响。最短路树有很多,任意求一个可以吗?可以,因为删除一条边后就可以走另一个最短路树了。枚举删除哪一条边并不好计算。考虑最后我们最短路一定是\(1\tol_x\tox\toy\tor_y\ton\)的样子,所以我们考......
  • 浅谈flex布局
    flex布局1.flex布局如何生效如图所示,在一个父盒子中有三个子盒子.代码如下:<divclass="bigbox"><span>1</span><span>2</span><span>3</span></div>大家看到这里不禁会有个疑问:为什么sp......
  • Manacher 学习笔记
    Manacher,又名马拉车算法,是一种能在\(O(n)\)的时间复杂度之内求出一个字符串的最长回文字串的巧妙算法,其与exKMP有一点相似之处Part1:实现步骤step1:改造字符串首先,我们要对字符串进行改造因为在原字符串中会有奇回文串和偶回文串,要分两种情况,不好处理,所以我们要改造......
  • Manacher 算法
    \(Manacher\)算法\(Manacher(马拉车)\)算法,是一种高效解决最长回文子串问题的算法。其\(O(n)\)的复杂度相较于暴力\(O(n^2)\)和字符串哈希\(O(nlogn)\)来说,快了不少。算法实现:首先说一下暴力的解法,对于每一个字符串上的字符,考虑以其为起点,向两边扩展。若字符串上回文......
  • 浅谈 K-D Tree 及其进阶应用
    前言\(\text{K-DTree(K-DimensionTree)}\)是一种可以有效处理高维信息的数据结构。在一般信息学竞赛题目中\(k=2\),此时它又称\(\text{2-DTree}\)。但遗憾的是,\(k\ge3\)的情况并不常见,这个我们后面再说明原因。算法描述问题首先从简单的情况考虑起,假设信息只有一......
  • 浅谈Java之UDP通信
    一、基本介绍        Java提供了用于处理UDP(用户数据报协议)的类和方法。UDP是一种无连接的网络协议,它允许发送端和接收端之间无需建立连接即可发送数据。在Java中,你可以使用java.net包中的DatagramSocket和DatagramPacket类来实现UDP通信。二、简单用法以下是使用......
  • 浅谈js中的部分方法
    hello!大家好,我是一名正在乱学前端技术的大学生,欢迎大家关注我,一起探讨前端技术,如有讲错的地方麻烦提出指正。letstr1="hello"//注:头尾有一个空格console.log(str1.charAt(1))//h,charAt返回字符串下标字符console.log(str1.replace('el','a'))//halo,rep......
  • 浅谈AI人工智能
    初识大模型和Python人工智能定义人工智能(ArtificialIntelligence,AI):用人工的方法,在机器上实现智能人工智能是研究、开发用于模拟、延伸和扩展人的智能理论、方法、技术及应用系统的一门新的技术科学,是计算机科学的一个分支。AI的技术划分机器学习算法机器学习概念是人工智......