P4445 最长回文串

P4445 最长回文串

题目描述

顺序和逆序读起来完全一样的串叫做回文串。比如acbcaacbcaacbca是回文串,而abcabcabc不是(abc的顺序为abcabcabc,逆序为cbacbacba,不相同)。

输入长度为nnn的串SSS,求SSS的最长双回文子串TTT,即可将TTT分为两部分XXXYYY(∣X∣,∣Y∣≥1∣X∣,∣Y∣≥1)(|X|,|Y|≥1∣X∣,∣Y∣≥1)X,Y1X,Y1XXXYYY都是回文串。

题目解答

将串sss进行预处理增加’$‘和’#'字符得到nsnsns串以便使用Manacher算法.

使用Manacher算法求以每个位置为中心的最长回文串长度数组npnpnp.

算法一.

根据数组ppp,处理出数组lft,rgtlft,rgtlft,rgt

lft[i]lft[i]lft[i]表示nsnsns中以iii为右端点的最长回文串的中心位置.

rgt[i]rgt[i]rgt[i]表示nsnsns中以iii为左端点的最长回文串的之心位置.

ps:由于nsnsns字符串中包含了#\##字符,因此回文串中心到一端的距离,就可以实际表示一个回文串的长度.

由于nsnsns串特殊的奇偶性,我们枚举iii,计算rgt[i+1]−lft[i]{rgt[i+1]-lft[i]}rgt[i+1]lft[i]的最大值就是答案.

问题变成了如何求lft,rgtlft,rgtlft,rgt数组.

lftlftlft为例,rgtrgtrgt求法类似:

枚举回文串中心的位置iii,则lft[i,i+np[i])lft[i,i+np[i])lft[i,i+np[i])区间内未设置值得位置全都设置成为iii.

实现代码

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>const int N = 100007;
char s[N],ns[N<<1];int np[N<<1];#define pr(x) std::cout << #x << ":" << x << std::endlstd::vector<int> vec[N<<1];
int vis[N<<1];int lft[N<<1],rgt[N<<1];int Manacher() {int len = 0,mx = 0,id;ns[len++] = '$';ns[len++] = '#';for(int i = 0;s[i];++i)ns[len++] = s[i],ns[len++] = '#';for(int i = 1;i < len;++i) {np[i] = mx > i ? std::min(np[2*id-i],mx-i):1;while(ns[i-np[i]] == ns[i+np[i]]) ++np[i];if(np[i]+i > mx) mx = np[i]+i,id = i;}int p = 0;for(int i = 0;i < len;++i) {for(;p < i + np[i];++p) {lft[p] = i;}}	p = len;for(int i = len-1;i > 0;--i) {for(;p > i - np[i];--p) {rgt[p] = i;}}int ans = 0;for(int i = 1;i < len;i++) {ans = std::max(ans,rgt[i+1] - lft[i]);}	return ans;
}int main() {std::cin >> s;std::cout << Manacher() << std::endl;return 0;
}

算法二.

计算数组lft,rgtlft,rgtlft,rgt

lft[i]lft[i]lft[i]表示以iii为右端点的最长回文子串在sss中的实际长度.

rgt[i]rgt[i]rgt[i]表示以iii为左端点的最长回文子串在sss中的实际长度.

那么答案就是枚举iii为偶数,ans=max(lft[i]+rgt[i+2])ans = max(lft[i] + rgt[i+2])ans=max(lft[i]+rgt[i+2])

lftlftlft为例,rgtrgtrgt类似:

从小到大枚举iii,并用一个优先队列维护当前最小的回文串中心点iii,设定在i+np[i]i+np[i]i+np[i]位置将优先队列中的iii设为失效.

每次从优先队列中取出的第一个有效的数即是lft[i]lft[i]lft[i].

这种算法的思路与算法一本质上是一样的,只不过枚举量不同,算法一枚举的是lft[i]lft[i]lft[i],然后利用单调性将时间复杂度降低到了O(n)O(n)O(n)

算法二枚举的是iii,需要用数据结构来维护,时间复杂度是O(nlogn)O(nlogn)O(nlogn)

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>const int N = 100007;
char s[N],ns[N<<1];int np[N<<1];#define pr(x) std::cout << #x << ":" << x << std::endlstd::vector<int> vec[N<<1];
int vis[N<<1];int lft[N<<1],rgt[N<<1];int Manacher() {int len = 0,mx = 0,id;ns[len++] = '$';ns[len++] = '#';for(int i = 0;s[i];++i)ns[len++] = s[i],ns[len++] = '#';for(int i = 1;i < len;++i) {np[i] = mx > i ? std::min(np[2*id-i],mx-i):1;while(ns[i-np[i]] == ns[i+np[i]]) ++np[i];if(np[i]+i > mx) mx = np[i]+i,id = i;}for(int i = 0;i < (N << 1);++i) vec[i].clear();memset(vis,0,sizeof(vis));	std::priority_queue<int,std::vector<int>,std::greater<int> > lQ;for(int i = 1;i < len;++i) {for(auto u : vec[i]) vis[u] = 1;while(!lQ.empty() && vis[lQ.top()]) lQ.pop();lft[i] = 1;if(lQ.empty()) {lQ.push(i);vec[i + np[i]].push_back(i);continue;}else {lft[i] = std::max(lft[i],(i-lQ.top()+1)/2*2+(lQ.top()%2==0));}lQ.push(i);vec[i + np[i]].push_back(i);}for(int i = 0;i < (N << 1);++i) vec[i].clear();memset(vis,0,sizeof(vis));	std::priority_queue<int> gQ;for(int i = len-1;i;--i) {for(auto u : vec[i]) vis[u] = 1;while(!gQ.empty() && vis[gQ.top()]) gQ.pop();rgt[i] = 1;if(gQ.empty()) {gQ.push(i);vec[i - np[i]].push_back(i);continue;}else {rgt[i] = std::max(rgt[i],(gQ.top()-i+1)/2*2+(gQ.top()%2==0));}gQ.push(i);vec[i - np[i]].push_back(i);}int ans = 0;for(int i = 1;i+2 <= len;++i) if(i%2==0)ans = std::max(ans,lft[i]+rgt[i+2]);return ans;
}int main() {std::cin >> s;std::cout << Manacher() << std::endl;return 0;
}

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

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

相关文章

RyuJIT的华丽转身

RyuJIT是作为.NET即时编译器的代号称谓&#xff0c;它是.NET运行时的基本组件之一。与此相反的是&#xff0c;Roslyn作为C#编译器&#xff0c;其编译C#代码成为IL字节码。然后&#xff0c;其再将IL字节码编译成相对于多种处理器的机器码。随着最近对dotnet/coreclr #18064的合并…

【树状数组】【dfs】树

树 题目大意&#xff1a; 有一棵树&#xff0c;当给一个点加上一个val时&#xff0c;他的儿子会减val&#xff0c;而他儿子的儿子会加上val&#xff08;-&#xff08;-val&#xff09;val&#xff09;&#xff0c;有m条指令&#xff0c;要不输出某个点的值&#xff0c;要不给…

SP1811-Longest Common Substring【SAM】

正题 题目链接:https://www.luogu.com.cn/problem/SP1811 题目大意 求两个串的最长公共子串。 解题思路 对与第一个串首先构建一个SAMSAMSAM&#xff0c;然后考虑让第二个串在上面匹配。 对于枚举的每个位置要在SAMSAMSAM上找一个节点使得它的后缀是枚举到的位置的后缀。所…

使用Nexus搭建私有Nuget仓库

前言Nuget是ASP .NET Gallery的一员&#xff0c;是免费、开源的包管理工具&#xff0c;专注于在.Net / .Net Core应用开发过程中第三方组件库的管理&#xff0c;相对于传统单纯的dll引用要方便、科学得多。其中nuget.org是最著名的Nuget公开库&#xff0c;但是企业内部开发的&a…

Wannafly挑战赛26 题解

Wannafly挑战赛26 题目连接 https://www.nowcoder.com/acm/contest/212#question A. 御坂网络 枚举圆心所在的位置,O(n)O(n)O(n) 检查即可,总时间复杂度为O(n2)O(n^2)O(n2) B. 冥土追魂 这题比较坑,我感觉题意叙述有问题,总之也是一道水题,题解略去. C. 七彩线段 题解 …

初一模拟赛总结(3.16)

成绩&#xff1a; rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4111lyflyflyf210210210303030100100100000808080222hkyhkyhky190190190100100100000101010808080333fyfyfy120120120100100100000202020000444tjhtjhtjh100100100100100100000000000555wjjwj…

牛客挑战赛43C-最优公式【二分】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7413/C 题目大意 给一个序列AAA&#xff0c;求两个a,ba,ba,b使得∑i1n∑j1nmax{∣Ai−a∣,∣Aj−b∣}\sum_{i1}^n\sum_{j1}^nmax\{|A_i-a|,|A_j-b|\}i1∑n​j1∑n​max{∣Ai​−a∣,∣Aj​−b∣}最小。 解题思路 因为是取…

好代码是管出来的——Git的分支工作流与Pull Request

上一篇文章好代码是管出来的——使用Git来管理源代码 介绍了常用的版本控制工具以及git的基本用法&#xff0c;从基本用法来看git与其它的版本控制工具好像区别不大&#xff0c;都是对代码新增、提交进行管理&#xff0c;可以查看提交历史、代码差异等功能。但实际上git有一个重…

牛客练习赛29 题解

牛客练习赛29 A. 可持久化动态图上树状数组维护01背包 题解 这题跟标题没有任何关系… 贪心的使得负数删除的时候下标尽可能大,然后正数的时候下标尽可能小. 观察到每个数下标最大的时候就是它的初始下标,下标的最小值是1. 然后贪心一下就好了. 代码 #include <iost…

【Floyed】小萨的烦恼(ssl 1624)

小萨的烦恼 ssl 1624 题目大意&#xff1a; 一个无向图&#xff0c;可以使其中一条道路的值除以2&#xff0c;求两个点之间的最短路 原题&#xff1a; Description 圣诞节又要到了&#xff01;小萨希望和自己心仪的MM一起出去度过一个浪漫的的圣诞节。他进行了详尽的准备…

好代码是管出来的——使用GitHub

前面的文章介绍了Git的基本概念和用法&#xff0c;本文则是基于GitHub的一个实践介绍&#xff0c;主要内容有&#xff1a;GitHub简介个人与组织仓库的创建与维护Fork与pull request小结GitHub简介GitHub是一个Git的远程代码托管平台&#xff0c;它除了提供代码托管外&#xff0…

Wannafly挑战赛24

Wannafly挑战赛24 题目连接 https://www.nowcoder.com/acm/contest/186#question A.石子游戏 题解 注意到当石子个数为偶数的时候,每回合都会减少一堆偶数石子,因此,先手必胜. 我们可以不考虑奇数堆石子,因为必胜方始终可以动偶数堆. 当必败方将奇数堆分成一堆偶数和一堆…

【模拟】正方形

正方形 题目大意&#xff1a; 有三个人&#xff0c;一人一笔的画正方形&#xff0c;每个正方形是上一个正方形每条边上的中点连接而成的&#xff0c;求每个人画了多长 原题&#xff1a; 题目描述 又到暑假啦&#xff0c;Conan, Ayumi, Mitsuhiko, Genta一起到Hakase家愉快…

P3975-[TJOI2015]弦论【SAM】

正题 题目链接:https://www.luogu.com.cn/problem/P3975 题目大意 给一个字符串sss和t,kt,kt,k。求字符串sss第kkk大的子串。 当T0T0T0时&#xff0c;相同的子串算一个当T1T1T1时&#xff0c;不同位置的相同子串算不同的串 解题思路 当T0T0T0时很简单&#xff0c;对于每个位…

【DP】跳格子

跳格子 题目大意&#xff1a; 有一堆格子&#xff0c;可以往前跳不超过当前格子上的数的步数&#xff0c;从1跳到最后一格最少要跳多少 原题&#xff1a; 题目描述 大家都说要劳逸结合&#xff0c;Ayumi, Mitsuhiko, Genta画完方格就出去运动啦&#xff01; 他们来到了一片…

.NET Core微服务之基于IdentityServer建立授权与验证服务

一、IdentityServer的预备知识要学习IdentityServer&#xff0c;事先得了解一下基于Token的验证体系&#xff0c;这是一个庞大的主题&#xff0c;涉及到Token&#xff0c;OAuth&OpenID&#xff0c;JWT&#xff0c;协议规范等等等等&#xff0c;园子里已经有很多介绍的文章了…

模拟退火求解TSP问题

模拟退火求解TSP问题 模拟退火算法步骤 1.寻找下一个解 2.计算下一个解的能量 3.决定是否接受这个解 4.降温 算法模板 double randfloat() {return rand()/(RAND_MAX0.0); }double T0 1000000,Tk 1,T T0,d 0.9999; int x initx();//当前解(初始解) int ansE,nowE;//全…

P2444-[POI2000]病毒【AC自动机】

正题 题目链接:https://www.luogu.com.cn/problem/P2444 题目大意 nnn个字符串&#xff0c;求有没有一个无限的字符串不包含任何一个给出的字符串。 解题思路 考虑ACACAC自动机的匹配方式&#xff0c;不过每次我们可以每次在构出的TrieTrieTrie树上随意走&#xff08;就是求完…

【模拟】2048

2048 题目大意&#xff1a; 模拟2048游戏 原题&#xff1a; 题目描述 此时&#xff0c;Conan却在一旁玩着2048。 这是一个4*4的矩阵&#xff0c;初始全为0。每次一个没有数字的格子中会随机出现一个2或4&#xff0c;每次可以选择上下左右其中一个方向去滑动&#xff0c;每…

在Docker中部署Asp.net core2.1以及修改发布

本篇文章主要是如何在Docker容器中运行ASP.NET Core应用程序&#xff0c;以及修改系统之后&#xff0c;发布更新。本文章采用自定义的Docker文件系统要求&#xff1a;1.服务器或本地已经安装docker一、创建一个Asp.Net Core 2.1 Web应用&#xff08;若可以熟练创建项目&#xf…