Codeforces 30 E
题意:
一个长度为奇数的回文串可以写成的形式,的长度也是奇数,为的反串。我们设,其中为任意可以为空的字符串。
给定,求原来回文串的最长长度,以及在中的起始位置和长度。
题解:
有一个关键的贪心结论:
假设我们已经定下了的中心点为,那么最长的原串,一定是让的长度尽可能长,其次让的长度尽可能长。
证明:
如果有可以去更短的串,分两种情况讨论:
- 和相邻:那么我们可以让为整个回文串,不影响答案。
- 其中一个和相邻、或两个都不和相邻:那如果不是以为中心最长的回文串,那么我们完全可以将向两侧各延伸一格,不会使得答案更劣。
所以,我们先求出以为中心最长回文串,设其长度为,这个可以使用manacher求出。(由于只要求长度为奇数的回文串,所以我们甚至没必要加分隔符)
然后我们枚举中心点,找到最长的。
发现是的一个后缀,那么我们就可以将模式串和匹配串进行KMP,得到表示以结尾的前缀 的后缀,最多能匹配多少的前缀。
那么我们求得的就是以结尾的最大长度。
所以为了求的的min,我们可以使用前缀max。注意也不能和相交,所以我们还要求从在最大时的起始位置,和取max,才是真正的长度。
时间复杂度为。
代码:
#include<bits/stdc++.h>
#define debug(...) std::cerr<<#__VA_ARGS__<<" : "<<__VA_ARGS__<<std::endl
const int maxn=100005;
int n,ans,x,y,p[maxn],nxt[maxn],f[maxn],id[maxn];
char str[maxn],istr[maxn];
void manacher() {
int mid=0,mr=0;
for(int i=1;i<=n;i++) {
if(i<=mr) p[i]=std::min(p[mid+mid-i],mr-i+1);
else p[i]=1;
while(i+p[i]<=n&&i-p[i]>=1&&str[i+p[i]]==str[i-p[i]]) p[i]++;
if(i+p[i]-1>mr) mr=i+p[i]-1,mid=i;
}
}
void kmp() {
for(int i=2,j=0;i<=n;i++) {
while(j&&istr[j+1]!=istr[i]) j=nxt[j];
if(istr[j+1]==istr[i]) j++;
nxt[i]=j;
}
for(int i=1,j=0;i<=n;i++) {
while(j&&istr[j+1]!=str[i]) j=nxt[j];
if(istr[j+1]==str[i]) j++;
f[i]=j;
if(j==n) j=nxt[j];
}
}
int main() {
scanf("%s",str+1); n=strlen(str+1);
for(int i=1;i<=n;i++) istr[i]=str[n-i+1];
manacher(); kmp();
for(int i=1;i<=n;i++)
if(f[i]>f[i-1]) id[i]=i;
else id[i]=id[i-1],f[i]=f[i-1];
for(int i=1;i<=n;i++) {
int longest=f[i-p[i]];
longest=std::min(longest,n-(i+p[i]-1));
int trans=2*longest+2*p[i]-1;
if(trans>ans) {
ans=trans;
x=id[i-p[i]],y=i;
}
}
std::pair<int,int> s1(x-f[x]+1,x),s2(y-p[y]+1,y+p[y]-1),s3(n-f[x]+1,n);
if(s1.first<=s1.second) {
printf("3\n%d %d\n%d %d\n%d %d\n",s1.first,s1.second-s1.first+1,
s2.first,s2.second-s2.first+1,s3.first,s3.second-s3.first+1);
} else {
printf("1\n%d %d\n",s2.first,s2.second-s2.first+1);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话