当前位置: 首页 > news >正文

题解:P12213 [蓝桥杯 2023 国 Python B] 最长回文前后缀

P12213 最长回文子串 题解

本解法有些复杂,同时需要哈希和 manacher ,欢迎来化简。

题意

输入字符串 \(S\) ,取其中一个前缀和后缀,拼接后为回文串。
某蒟蒻(我)原来还以为可以把后缀放在前面

本文作者是 MZMTab@ https://www.luogu.com.cn/user/1046687 ,原文https://www.luogu.com.cn/article/9izblypr 和 https://www.cnblogs.com/MZMTab/p/19616536 如果您能直接看到这段文字而在本页没有转载提示,或以“原创”名义发出,说明您访问的是侵权内容,请联系管理员删除文章并处罚侵权人,十分感谢您的见义勇为之举。

思路

为了方便,以下令 \(n=|S|\) ,即字符串长度。

1. 先考虑暴力

依次枚举前缀和后缀,再用双指针判断其是否为回文 。
一共有 \(n\) 个前缀和 \(n\) 个后缀,双指针判断为 \(O(n)\) 复杂度,总复杂度为 \(O(n^3)\) 。预计得分 30 分。

2. 优化判断

由于字符串是固定的,可以预处理其哈希前缀和后缀,
再按前缀和后缀拼接后的中心分成前后两部分,合并哈希值,判断是否相等。
合并的具体方法可以参考 P4503 [CTSC2014] 企鹅 QQ 和 P6739 [BalticOI 2014] Three Friends (Day1)
总复杂度 \(O(n^2)\) 。预计得分 60 分。

3. 正解

由回文串,容易想到 manacher 算法。由样例 aababa 推测,拼接后的回文串可能含原字符串的回文子串。令前缀为 \(S_{[1 ,l_1]}\) ,后缀为 \(S[n-l_2+1,n]\) ,考虑拼接后回文中心位置。

1、 \(l_1=l_2\)

此时回文中心在前后缀之间。判断前后缀的哈希值是否相等即可。

2. \(l_1\neq l_2\)

此时回文中心在前缀或后缀中。下面以在前缀为例。如图

在跑 manacher 时,得到最长以 \(C\) 为中心的最长回文子串为 \([L,R]\) 如果取前缀 \([1 \ldots R]\) 和一个比它短的后缀,则回文中心一定在 \(C\) 处。此时只需要两个橘色部分相等即可。
而如果我只要该回文子串的部分,如 \([L' \ldots R']\) ,则需要 \([1 \ldots L']\) 有对应的后缀,条件更严格,且拼出的回文串长度与取 \([1 \ldots R]\) 一定相同。故不需要考虑
所以我们只需要考虑以每个位置为回文中心的最长回文子串,用哈希表存初所有前缀和后缀哈希值来判断即可,复杂度 \(O(n)\)
需要注意来跑 manacher 的处理过的串与与原串的对应关系,详见代码

AC代码

本文作者是 MZMTab@ https://www.luogu.com.cn/user/1046687 ,原文https://www.luogu.com.cn/article/9izblypr 和 https://www.cnblogs.com/MZMTab/p/19616536 如果您能直接看到这段文字而在本页没有转载提示,或以“原创”名义发出,说明您访问的是侵权内容,请联系管理员删除文章并处罚侵权人,十分感谢您的见义勇为之举。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=1e5+100;
const ull mod=3326955323;
int n,k;
char a[N];
char s[N<<1];
int p[N<<1];
ull base1,base2;
ull p1[N],p2[N];
ull fh1[N],fh2[N],th1[N],th2[N];
unordered_set<ull> ff,tt;
int ans=0;
void init(){base1=(rand()%100+30)|1;base2=(rand()%100+40);p1[0]=p2[0]=1;for(int i=1;i<=n;i++){ p1[i]=p1[i-1]*base1;p2[i]=p2[i-1]*base2%mod;}ull tmp=0;ff.insert(0);tt.insert(0);//注意空串 for(int i=1;i<=n;i++){fh1[i]=fh1[i-1]*base1+a[i]-'a'+1;fh2[i]=(fh2[i-1]*base2+a[i]-'a'+1)%mod;ff.insert(fh1[i]*mod+fh2[i]);//由于unordered_set不能用pair,所以将两个哈希值哈希成一个值 }for(int i=n;i>=1;i--){th1[i]=th1[i+1]*base1+a[i]-'a'+1;th2[i]=(th2[i+1]*base2+a[i]-'a'+1)%mod;tmp=th1[i]*mod+th2[i];tt.insert(tmp);if(ff.count(tmp)){ans=max(ans,(n-i+1)*2);//中心在前缀和后缀之间的情况 }}//注意下标 s[k++]='&';//0s[k++]='#';//1for(int i=1;i<=n;i++){//1 2 3 ...s[k++]=a[i];//2*i   2 4 6 ...s[k++]='#'; //2*i+1 3 5 7 ...}s[k++]='$';
}
int main(){scanf("%s",a+1);n=strlen(a+1);init();int r=0,c=0;for(int i=1;i<k-1;i++){if(i<r) p[i]=min(p[(c<<1)-i],r-i);else p[i]=1;while(s[i+p[i]]==s[i-p[i]]) p[i]++;if(r<i+p[i]){r=i+p[i];c=i;}
//		cout<<i<<' '<<s[i]<<":"<<p[i]<<endl;if(s[i]=='#'&&p[i]==1) continue;//在原串无对应 int t;t=i-p[i]+1;(t+=1)>>=1;//这部分可以手推以下,比较容易 
//		cout<<"\t"<<t<<" "<<a[t]<<" "<<p[i]+t*2-3<<endl;if(tt.count(fh1[t-1]*mod+fh2[t-1])){ans=max(ans,p[i]+t*2-3); } t=i+p[i]-1;t>>=1;
//		cout<<"\t"<<t<<" "<<a[t]<<" "<<p[i]-1+(n-t)*2<<endl;if(ff.count(th1[t+1]*mod+th2[t+1])){ans=max(ans,p[i]-1+(n-t)*2);}}printf("%d",ans);return 0;
}
本文作者是 MZMTab@ https://www.luogu.com.cn/user/1046687 ,原文https://www.luogu.com.cn/article/9izblypr 和 https://www.cnblogs.com/MZMTab/p/19616536 如果您能直接看到这段文字而在本页没有转载提示,或以“原创”名义发出,说明您访问的是侵权内容,请联系管理员删除文章并处罚侵权人,十分感谢您的见义勇为之举。
http://www.jsqmd.com/news/382615/

相关文章:

  • 沃尔玛购物卡怎么处理划算?这些妙招让你轻松回血! - 京顺回收
  • 想用U盘,必须使用windows7
  • 数字员工推动AI销冠系统与AI提效软件系统实现高效业务转型
  • 教鞭神器,网课老师必备
  • 北方水垢重灾区选购建议:2026 强力阻垢净水器排行,菲浦斯领先 - 水业策论
  • AutoGLM-Phone 9B 端侧智能体:基于 vLLM 与 Docker 的云端部署与 ADB 联调指南 - 实践
  • Win11关闭自动更新,windows11如何永久禁止自动更新
  • GTK4 GObject深度剖析
  • 【高效】Win11如何禁止系统自动更新 Win11关闭系统自动更新的方法
  • Zig 简介:C 的现代化继任者
  • 【信息科学与工程学】信息科学领域第四十八篇 计量工程
  • 智慧交通沥青路面损伤缺陷检测数据集VOC+YOLO格式547张4类别
  • web ui 测试显式等待深度解析
  • 题解:P15301 [ROI 2012 Day 2] army 汗国军队
  • CMake:现代C/C++工程的构建中枢
  • web ui 测试隐式等待深度解析
  • web ui 测试智能等待深度解析
  • Hive SQL优化:分区表+分桶表提升查询效率
  • 医疗仪器整机研发设计怎么做?2026创新合规智能化趋势指南|新纪元必读 - 匠言榜单
  • Nightwatch.js深度解析
  • 【Docker进阶篇】Docker Compose 实战:一键启动Web+数据库+缓存,微服务环境部署不再绕弯
  • C++中链表的虚拟头结点:应用场景与运用时机
  • 2026年 电感厂家推荐排行榜:共模电感/贴片电感/PFC电感/扁平线共模电感/工字电感/贴片功率电感/贴片绕线电感/色环电感/磁环电感/大电流电感/数字功放电感 - 品牌企业推荐师(官方)
  • 【Docker进阶篇】Docker Compose实战:Spring Boot与Redis服务名通信全解析
  • langGraph从入门到精通(四)——基于LangGraph的State状态模式设计 - 指南
  • 关于凸性的 things(wqs + slope trick + 闵可夫斯基和)
  • 【Docker进阶篇】拒绝重复构建镜像!.env文件+Profile实现多环境无缝切换
  • 华为OD机考双机位C卷 - 测试用例执行计划 (Java Python JS GO C++ C)
  • 手摸手在扣子平台搭建周报智能体[特殊字符]
  • 华为OD机考双机位C卷 - 相对开音节 (Java Python JS GO C++ C)