Manacher

Manacher(马拉车算法)

Manacher算法主要用于求解回文串问题,能够统计出以每一个位置为中心的回文串的个数,效率极高。

模板

题目描述

Manacher算法的实现过程:
1.在字符串每两个字符之间插入一个分隔符。
2.iii111nnn求解P[i]P[i]P[i]表示以iii为中心的最长回文子串长度,同时记录一个当前延伸最远的回文子串,记它的右端点为rightrightright,中心点为midmidmid,则求P[i]P[i]P[i]时,若right>iright>iright>i,那么P[i]的长度至少为min(right−i,P[mid−(i−mid)])P[i]的长度至少为min(right-i,P[mid-(i-mid)])P[i]min(righti,P[mid(imid)]),然后再暴力地向两边拓展即可。

时间复杂度为均摊O(n)O(n)O(n)

// luogu-judger-enable-o2
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=1e9+7;
const int MAXN=20000005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
char st[MAXN],s[MAXN];
int P[MAXN];
int main()
{scanf("%s",st);int lenst=strlen(st);s[0]='%',s[1]='#';for (int i=0;i<lenst;i++) s[i*2+2]=st[i],s[i*2+3]='#';int lens=lenst*2+1;int mid=0,right=0;int smax=0;for (int i=1;i<=lens;i++){P[i]=(right>i?min(P[mid*2-i],right-i):1);while (s[i-P[i]]==s[i+P[i]]) P[i]++;if (right<i+P[i]) right=i+P[i],mid=i;smax=max(smax,P[i]);}printf("%d\n",smax-1);return 0;
}

一道例题

CF30E. Tricky and Clever Password

Solution

其实这并不是一道Manacher题,只是需要一步Manachcer预处理。

我们发现最后一个串suffixsuffixsuffix一定是原串的一个后缀,因此我们考虑枚举suffixsuffixsuffix的长度,找到最前面的一个prefixprefixprefix,使得prefixprefixprefixsuffixsuffixsuffix的反串,这一部分可以用KMP实现。

在找到prefix,suffixprefix,suffixprefix,suffix以后,我们还需要找一个最优的middlemiddlemiddle,它是一个长度为奇数的回文串,并包含在[preffix+1,suffix−1][preffix+1,suffix-1][preffix+1,suffix1]之间,但我们直接求这里面的最长回文子串是不行的,因为其中的最长回文子串可能会与preffixpreffixpreffixsuffixsuffixsuffix重合,因此考虑二分答案,则问题变成了判断[preffix+1+mid,suffix−1−mid][preffix+1+mid,suffix-1-mid][preffix+1+mid,suffix1mid]之间是否有最长回文子串长度大于midmidmid

这就变成了一个区间最长回文子串最大值,Manacher求出P[i]P[i]P[i]之后,STSTST表预处理就能够O(1)O(1)O(1)询问了。

总时间复杂度为O(nlgn)O(nlgn)O(nlgn)

个人实现比较丑陋。。。

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=998244353;
const int MAXN=600005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
struct Ansnode{ int l,mid,len,c; } Ans; 
char s[MAXN],t[MAXN],St[MAXN];
PR mx[MAXN][20];
int Log[MAXN],nxt[MAXN],P[MAXN];
void InitKMP(char *st,int len)
{for (int i=2,j=0;i<=len;i++){while (j&&st[i]!=st[j+1]) j=nxt[j];if (st[i]==st[j+1]) j++;nxt[i]=j;
//		cout<<"Nxt:"<<i<<" "<<nxt[i]<<endl;}
}
void Manacher(char *st,int len)
{St[0]='%',St[1]='#';for (int i=1;i<=len;i++) St[i<<1]=st[i],St[i<<1|1]='#';
//	cout<<St<<endl;int Len=len<<1|1,mid=0,right=0;for (int i=1;i<=Len;i++){P[i]=(right>i?min(P[mid*2-i],right-i):1);while (St[i-P[i]]==St[i+P[i]]) P[i]++;
//		cout<<i<<" "<<P[i]<<endl;if (right<i+P[i]) right=i+P[i],mid=i;}for (int i=1;i<=len;i++) {if (P[i*2]-1>=Ans.c) Ans=(Ansnode){0,i,0,P[i*2]-1};P[i]=P[i*2]>>1;
//		cout<<P[i]<<endl;}
}
PR max(PR x,PR y){ return x.fi>=y.fi?x:y; }
void InitST(int n)
{Log[1]=0;for (int i=2;i<=n;i++) Log[i]=Log[i>>1]+1;for (int i=1;i<=n;i++) mx[i][0]=MP(P[i],i);for (int i=1;i<=Log[n];i++)for (int j=1;j<=n-(1<<i)+1;j++) mx[j][i]=max(mx[j][i-1],mx[j+(1<<(i-1))][i-1]);
}
PR querymx(int l,int r)
{if (l>r) return MP(-100000,0);int t=Log[r-l+1];return max(mx[l][t],mx[r-(1<<t)+1][t]);
}
PR getans(int L,int R)
{if (L>R) return MP(-100000,0);int l=1,r=(R-L)/2+1;while (l<r){int mid=(l+r+1)>>1;if (querymx(L+mid-1,R-mid+1).fi>=mid) l=mid;else r=mid-1;}return MP(l,querymx(L+l-1,R-l+1).se);
}
int main()
{scanf("%s",t+1);int len=strlen(t+1);for (int i=1;i<=len;i++) s[i]=t[len-i+1];InitKMP(s,len);Manacher(t,len);InitST(len);int ans=0;for (int l=1,i=1,j=0;l<=len;l++){
//		cout<<l<<" "<<i<<" "<<j<<" "<<t[i+1]<<" "<<s[j+1]<<endl;for (;i<=len;i++){while (j&&t[i]!=s[j+1]) j=nxt[j];if (t[i]==s[j+1]) j++;if (j==l){PR q=getans(i+1,len-l);
//				cout<<i+1<<" "<<len-l<<" "<<j<<":"<<q.fi<<" "<<q.se<<endl;if (q.fi+q.fi+l+l-1>Ans.c) Ans=(Ansnode){i-l+1,q.se,l,q.fi+q.fi+l+l-1};i++;break;}}}if (!Ans.len) { puts("1"); printf("%d %d\n",Ans.mid-(Ans.c-1)/2,Ans.c); }else { puts("3"); int q=Ans.c-Ans.len*2;printf("%d %d\n",Ans.l,Ans.len);printf("%d %d\n",Ans.mid-(q-1)/2,q);printf("%d %d\n",len-Ans.len+1,Ans.len);}return 0;
}
/*
xjowabclwjegohghlewcba
*/

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

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

相关文章

.NET/C# 使用 ConditionalWeakTable 附加字段(CLR 版本的附加属性,也可用用来当作弱引用字典 )...

如果你使用过 WPF/UWP 等 XAML UI 框架&#xff0c;那么应该了解到附加属性的概念。那么没有依赖属性支持的时候如何做附加属性的功能呢&#xff1f;你可能会想到弱引用。但这需要做一个弱引用字典&#xff0c;要写的代码还是非常麻烦的。本文介绍 .NET 的 ConditionalWeakTabl…

P4548 [CTSC2006]歌唱王国

P4548 [CTSC2006]歌唱王国 题目描述 Solution 这一题在《具体数学&#xff08;混泥土数学&#xff09;》里讲得很详细了啊&#xff0c;这里相当于总结一下&#xff0c;想具体了解的直接看书吧。 我们先考虑字符集为222的情况&#xff0c;设硬币正面朝上(H)(H)(H)的概率为pp…

在C#中使用Json.Net进行序列化和反序列化及定制化

序列化&#xff08;Serialize&#xff09;是将对象转换成字节流&#xff0c;并将其用于存储或传输的过程&#xff0c;主要用途是保存对象的状态&#xff0c;以便在需要时重新创建该对象&#xff1b;反序列化&#xff08;Deserialize&#xff09;则是将上面的字节流转换为相应对…

SRM614 Div1 Hard

SRM614 Div1 Hard 题目描述 Solution 显然有&#xff1a; E(x,y)(E(x−1,y)E(x,y−1))/21E(x,y)(E(x-1,y)E(x,y-1))/21 E(x,y)(E(x−1,y)E(x,y−1))/21 直接高斯消元时间复杂度O((nm)3)O((nm)^3)O((nm)3)。 可以发现这种做法十分浪费&#xff0c;消元之后会有大量冗余元素&…

知乎个人精选 | 绝版的专业书到哪里找最快最高效?

估计书到用时方恨少是很多软件开发人员的苦恼&#xff0c;当然我这里提到的"少"表示稀少&#xff0c;买不到之意~比如你加入一家政府机构或给为政府机构服务的公司做开发&#xff0c;主要做传统软件&#xff0c;对方需要使用 Win Forms做开发&#xff0c;你打算系统性…

HUD4035Maze

HUD4035Maze 题目描述 Solution 很容易写出期望的式子&#xff1a; 令fif_ifi​表示从iii号节点开始期望几步走出迷宫。 令pi1−ki−eip_i1-k_i-e_ipi​1−ki​−ei​表示选择走向其他边的概率。 令did_idi​表示iii号结点的度数。 fikif1pi∑fjdi10eiAnsf1f_ik_if_1p_i\sum…

正反案例介绍SOLID原则

一.概述SOLID五大原则使我们能够管理解决大多数软件设计问题。由Robert C. Martin在20世纪90年代编写了这些原则。这些原则为我们提供了从紧耦合的代码和少量封装转变为适当松耦合和封装业务实际需求的结果方法。使用这些原则&#xff0c;我们可以构建一个具有整洁&#xff0c;…

LOJ#2145. 「SHOI2017」分手是祝愿

LOJ#2145. 「SHOI2017」分手是祝愿 题目描述 Solution 首先有一个结论&#xff1a; 灯的状态序列a1,a2...ana_1,a_2...a_na1​,a2​...an​唯一对应了一个最优操作序列b1,b2...bnb_1,b_2...b_nb1​,b2​...bn​。 因为编号最大的灯只能由开关自己来改变。 因此&#xff0c;…

ASP.NET Core 中的静态文件

1.前言当我们创建Core项目的时候&#xff0c;Web根目录下会有个wwwroot文件目录&#xff0c;wwwroot文件目录里面默认有HTML、CSS、IMG、JavaScript等文件&#xff0c;而这些文件都是Core提供给客户端使用的静态文件。但是这些静态文件需要在Core里面配置才可以对外公开访问。2…

LOJ#2542. 「PKUWC2018」随机游走

LOJ#2542. 「PKUWC2018」随机游走 题目描述 Solution 去过一个点集中所有节点的期望时间不好求&#xff0c;考虑min−maxmin-maxmin−max容斥&#xff0c;转化为求第一次到达某一个点集的期望时间。 我们对于每一个点集sss&#xff0c;都求出fif_ifi​表示从iii结点到点集s…

基于Kebernetes 构建.NET Core技术中台

今天下午在腾讯云社区社区分享了《基于Kubernetes 构建.NET Core技术中台》&#xff0c;下面是演讲内容的文字实录。我们为什么需要中台我们现在处于企业信息化的新时代。为什么这样说呢&#xff1f;过去企业信息化的主流重心是企业内部信息化。但现在以及未来的企业信息化的主…

P3706 [SDOI2017]硬币游戏

P3706 [SDOI2017]硬币游戏 题目描述 Solution 前置技能&#xff1a; P4548 [CTSC2006]歌唱王国 歌唱王国就是n1n1n1的情况。 我们用类似的方法&#xff0c;先考虑两个串的情况。 设SAS_ASA​表示AAA串最先选到的概率&#xff0c;设SBS_BSB​表示BBB串最先选到的概率。 则…

RedLock 实现分布式锁

并发是程序开发中不可避免的问题&#xff0c;根据系统面向用户、功能场景的不同&#xff0c;并发的重视程度会有不同。从程序的角度来说&#xff0c;并发意味着相同的时间点执行了相同的代码&#xff0c;而有些情况是不被允许的&#xff0c;比如&#xff1a;转账、抢购占库存等…

AGC030D - Inversion Sum

AGC030D - Inversion Sum 题目描述 Solution 考虑dpdpdp&#xff0c;fi,jf_{i,j}fi,j​表示第iii个位置的数大于第jjj个位置的数的概率。 对于每一个询问修改贡献即可。 时间复杂度O(nqn2)O(nqn^2)O(nqn2)。 #include <vector> #include <list> #include <m…

[翻译] NumSharp的数组切片功能 [:]

原文地址&#xff1a;https://medium.com/scisharp/slicing-in-numsharp-e56c46826630翻译初稿&#xff08;英文水平有限&#xff0c;请多包涵&#xff09;&#xff1a;由于Numsharp新推出了数组切片这个牛逼的功能&#xff0c;所以.NET社区距离拥有强大的开源机器学习平台又近…

P3978 [TJOI2015]概率论

P3978 [TJOI2015]概率论 题目描述 Solution 设CnC_nCn​表示nnn个节点的树的个数&#xff08;卡特兰数&#xff09;&#xff0c;SnS_nSn​表示nnn个节点的所有树的叶子的个数和。 Cn∑i0n−1CiCn−i−1[n0]Sn2∑i0n−1SiCn−i−1[n1]C_n\sum_{i0}^{n-1} C_iC_{n-i-1}[n0]\\ …

Visual Studio 2019 16.1发布,更快更高效

Visual Studio 2019 16.1 已正式发布&#xff0c;可以看到&#xff0c;新版本的启动速度有了显著的提升&#xff0c;还节省了不少的内存空间。主要更新如下&#xff1a;IDE现已公开发布 Visual Studio IntelliCode&#xff0c;并且可以随任何支持 C#、C、TypeScipt/JavaScript …

牛顿迭代法

牛顿迭代法 定义 在一般意义下&#xff0c;牛顿迭代法可以求出一个函数的零点&#xff0c;而在多项式意义下&#xff0c;牛顿迭代能够求出&#xff1a;给定一个G(x)G(x)G(x)&#xff0c;求F(x)F(x)F(x)&#xff0c;使得G(F(x))≡0(modxn)G(F(x)) \equiv 0\;\;\;(mod\;\;x^n)G…

.NET Core 3.0之创建基于Consul的Configuration扩展组件

经过前面三篇关于.NET Core Configuration的文章之后&#xff0c;本篇文章主要讨论如何扩展一个Configuration组件出来。如果前面三篇文章没有看到&#xff0c;可以点击如下地址访问.NET Core 3.0之深入源码理解Configuration(一).NET Core 3.0之深入源码理解Configuration(二)…

Mono 和 .NET Core比翼双飞

大家好&#xff0c;今天给大家分享.NET 蓝图之下的Mono和.NET Core 话题&#xff0c;微软在Build 2019 大会上给.NET 做了一个五年规划&#xff0c;所以分享的主题就是《Mono和.NET Core 比翼双飞》&#xff0c;将在完成这个五年规划的时候合体。在开始这个主题之前&#xff0c…