Palindromic Problem
主要是复习二分+哈希的思想,考虑贡献的思想也比较自然,题目也不是很难
然后想一下怎么 用差分维护一次项系数和常数项系数,具体下面的代码
#include<bits/stdc++.h>
#define ll long long
#define ULL unsigned long long
using namespace std;
const ULL mod=1721;
const int N=3e5+5;
ULL power[N];
char s[N];
ULL Hash1[N],Hash2[N];
int l;
ll cnt[N][30],sum[3][N][3],d[3][N][3];
ll Sum;
int main()
{
power[0]=1;
for(int i=1;i<=N-5;i++)
power[i]=power[i-1]*mod;
scanf("%d",&l);
scanf("%s",s);
Hash1[0]=Hash2[l+1]=0;//hash1是前缀哈希,hash2是后缀哈希
for(int i=0;i<l;i++)
Hash1[i+1]=Hash1[i]*mod+(ULL)(s[i]-'a'+1);
for(int i=l-1;i>=0;i--)
Hash2[i+1]=Hash2[i+2]*mod+(ULL)(s[i]-'a'+1);
for(int i=1;i<=l;i++)
{
//这一部分以某一字符为中心
int L=0,r=min(i-1,l-i),mid,x,y=0;
while(L<=r)
{
mid=L+r>>1;
if(Hash1[i-1]-Hash1[i-mid-1]*power[mid]==Hash2[i+1]-Hash2[i+mid+1]*power[mid])
{
x=mid;
L=mid+1;
}
else r=mid-1;
}
Sum+=x+1;
L=0,r=min(i-x-2,l-i-x-1);
while(L<=r)
{
mid=L+r>>1;
if(Hash1[i-x-2]-Hash1[i-x-mid-2]*power[mid]==Hash2[i+x+2]-Hash2[i+x+mid+2]*power[mid])
{
y=mid;
L=mid+1;
}
else r=mid-1;
}
//cnt[i][j]是将第i个字符修改为j的增量
if(i+x<l&&i-x-2>=0)
{
cnt[i-x-1][s[i+x]-'a']+=y+1;
cnt[i+x+1][s[i-x-2]-'a']+=y+1;
}
//d[0/1][i][0/1]表示的是如果修改第i个字符的减少量
//第一维表示是前缀差分还是后缀差分
//第三维表示是常数项系数还是一次项系数
d[0][i-x][1]++,d[0][i][1]--;
d[0][i-x][0]+=x+1-i,d[0][i][0]-=x+1-i;
d[1][i+x][1]--,d[1][i][1]++;
d[1][i+x][0]+=x+1+i,d[1][i][0]-=x+1+i;
if(i==1) continue;
//这一部分是以两个字符的中间为中心
L=0,r=min(i-1,l-i+1),x=0;
while(L<=r)
{
mid=L+r>>1;
if(Hash1[i-1]-Hash1[i-mid-1]*power[mid]==Hash2[i]-Hash2[i+mid]*power[mid])
{
x=mid;
L=mid+1;
}
else r=mid-1;
}
Sum+=x;
L=0,r=min(i-x-2,l-i-x),y=0;
while(L<=r)
{
mid=L+r>>1;
if(Hash1[i-x-2]-Hash1[i-x-mid-2]*power[mid]==Hash2[i+x+1]-Hash2[i+x+mid+1]*power[mid])
{
y=mid;
L=mid+1;
}
else r=mid-1;
}
if(i+x-1<l&&i-x-2>=0)
{
cnt[i-x-1][s[i+x-1]-'a']+=y+1;
cnt[i+x][s[i-x-2]-'a']+=y+1;
}
d[0][i-x][1]++,d[0][i][1]--;
d[0][i-x][0]+=x+1-i,d[0][i][0]-=x+1-i;
d[1][i+x-1][1]--,d[1][i-1][1]++;
d[1][i+x-1][0]+=x+i,d[1][i-1][0]-=x+i;
}
for(int i=1;i<=l;i++)
for(int j=0;j<=1;j++)
sum[0][i][j]=sum[0][i-1][j]+d[0][i][j];
for(int i=l;i>=1;i--)
for(int j=0;j<=1;j++)
sum[1][i][j]=sum[1][i+1][j]+d[1][i][j];
for(int i=1;i<=l;i++)
cnt[i][26]=(sum[0][i][1]+sum[1][i][1])*i+sum[0][i][0]+sum[1][i][0];
ll Max=-1;
for(int i=1;i<=l;i++)
for(int j=0;j<26;j++)
Max=max(Max,cnt[i][j]-cnt[i][26]);
if(Max<0)
{
printf("%lld\n",Sum);
printf("%s",s);
return 0;
}
else if(!Max)
{
printf("%lld\n",Sum);
for(int i=1;i<=l;i++)
for(int j=0;j<26;j++)
if(cnt[i][j]-cnt[i][26]==Max)
{
if(s[i-1]>j+'a')
{
for(int k=0;k<i-1;k++)
printf("%c",s[k]);
printf("%c",j+'a');
for(int k=i;k<l;k++)
printf("%c",s[k]);
return 0;
}
}
printf("%s",s);
return 0;
}
int last;
for(int i=1;i<=l;i++)
for(int j=0;j<26;j++)
if(cnt[i][j]-cnt[i][26]==Max) last=i;
for(int i=1;i<=l;i++)
for(int j=0;j<26;j++)
if(cnt[i][j]-cnt[i][26]==Max)
{
if(s[i-1]>j+'a'||i==last)
{
printf("%lld\n",Sum+Max);
for(int k=0;k<i-1;k++)
printf("%c",s[k]);
printf("%c",j+'a');
for(int k=i;k<l;k++)
printf("%c",s[k]);
return 0;
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构