P9753 [CSP-S 2023] 消消乐 题解

P9753

法一:

这是赛时想法。

考虑 dp。

fi 表示 i 为右端点的合法子串个数,则答案为 i=1nfi

赛时想过匹配指针不断跳的,但当时没敢写,用了一种更直观的方法。

仿照于括号序列,合法的子串只能为 cAcAB,因此找到一个最右的位置 l 使满足 li 这一段合法,然后就可以用 AB 拼接了。令 prei,c 表示前 i 个字符中,能与 c 匹配的最靠后的位置。即找到是否存在以 i1 为右端点且满足条件的子串 S,使得 S 前面是 si。若有多个满足条件的 S,找到左端点最大的 pos。则 fi=fpos1+1,因为以 pos1 的合法子串与 S 拼起来一定合法。注意这里的 S 可能为空

最后注意一下最后答案需要 long long。

代码:

typedef long long ll;
const int N=2e6+10;
int n;string s;ll ans;
int pre[N][26],f[N];
int main(){
	cin>>n>>s;s=" "+s;
	for(int i=1;i<=n;i++){
		if(pre[i-1][s[i]-'a']){
			int lst=pre[i-1][s[i]-'a'];
			for(int j=0;j<26;j++)pre[i][j]=pre[lst-1][j];
			f[i]=f[lst-1]+1;
			ans+=f[i];
		}
		pre[i][s[i]-'a']=i;
	}
	cout<<ans<<"\n";
	return 0;
}

法二:

看到这个像括号序列的东西,可以想到用栈,相同后弹出。

发现当两个点的栈相同时这个段一定合法,用 map 维护哈希即可。

posted @   Pengzt  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示