bzoj3790 神奇项链

博客记录了使用贪心算法解决回文串覆盖问题的方法。从左往右扫描,每个回文左端点记录右端点位置,用last和maxR分别记录上次和移动过程中的最右端。当i越过last时记录回文串,最后得出整个串覆盖至少需(ans + 1)个回文串,需连接ans次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门
记一下贪心的方法:从左往右扫。每个回文左端点记录了回文右端点的位置。
l a s t last last记录上次的最右端。 m a x R maxR maxR记录从 i i i往右走到 l a s t last last过程中的最右端。
初始化 l a s t = m a x R = T [ 0 ] last=maxR=T[0] last=maxR=T[0] m a x R maxR maxR会在移动的过程中不断更新。
i i i越过 l a s t last last时,表示已经跨过覆盖的最大范围了。ans+=1,记录跨过的这个回文串。
然而最后一个串的右端点一定在整个串的右端点。跨过了之后退出循环。ans记录不到。
所以整个串覆盖至少需要(ans+1)个回文串。需要连接ans次。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
char s[maxn];int R[maxn],N,T[maxn],now,to,ans=0,last,maxR;
inline void manacher(){
	int p=0,mx=0;
	for(int i=0;i<=N;++i){
		R[i]=(mx>i)?(min(mx-i+1,R[p*2-i])):1;
		while(i>=R[i]&&s[i+R[i]]==s[i-R[i]]) R[i]++;
		if(i+R[i]-1>mx) mx=i+R[i]-1,p=i;
		T[i-R[i]+1]=max(T[i-R[i]+1],i+R[i]-1);
	}
}
int main(){
	while(scanf("%s",s)!=EOF){
		memset(T,0,sizeof(T)),N=strlen(s),now=0,ans=0;
		for(int i=N-1;i>=0;i--) s[(i+1)<<1]='#',s[(i<<1)+1]=s[i];
		s[0]='#',N<<=1,manacher();
		last=maxR=T[0];
		for(int i=0;i<=N;i+=2){
			if(i>last) ans++,last=maxR;
			maxR=max(maxR,T[i]);
		}printf("%d\n",ans);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值