程序设计CSP-M3-补题——T3-咕咕东学英语

题目描述

一个只有大写A、B的序列,求这个序列有多少个子串是Delicious的。
Delicious:对于一个字符串,它是Delicious的,当且仅当它的每一个字符都属于一个长度大于1的回文子串。

Input

第一行一个整数n,代表序列长度
第二行一个只含AB的字符串

Output

满足题意的子串个数

解题思路

对于这道题,我一开始是从正面下手,即找满足条件的子串有哪些规律、特征,然后来选择;但情况较为复杂,在要求时间内,并没有有效完成。后来与别人交流过程中了解到,可以从反面下手,把不满足条件的减去,会更方便。
对于一个长度为n的字符串,可供我们选择的子串共有n*(n-1)/2个,这是总数;而不符合条件的子串,有以下四种情况:
AA……B
BB……A
ABB……B
BAA……A
不难发现,后两种正是倒序的前两种的情况,因此我们只需从正序和倒序,找到AB相异的情况,然后从总数中减去该子串的长度,最后,由于正序和倒序过程中,会将AB、BA减去两次,因此我们只需在第一次正序遍历过程中,记下AB、BA的个数,最后在ans中再加上,即可得到最终答案。

实现代码

#include<iostream>
#include<string>
using namespace std;

string s;
long long n,ans;

int main()
{
	cin>>n>>s;
	char flag=s[0];
	long long cnt=0,index=0;
	ans=(n-1)*n/2;
	for(long long i=1;i<n;++i)
	{
		if(s[i]!=flag)
		{
			flag=s[i];
			ans-=(i-index);
			index=i;
			cnt++;
		}
	}
	flag=s[n-1];
	index=n-1;
	for(long long i=n-2;i>=0;--i)
	{
		if(s[i]!=flag)
		{
			flag=s[i];
			ans-=(index-i);
			index=i;
		}
	}
	ans+=cnt;
	cout<<ans<<endl;
	return 0;
}

总结

这道题还是很注重思考的,一开始贸然的从正面入手,很容易陷入一个大坑,难以完整解答;当遇到这种情况时,学会从反面入手,想想不满足题意的情况,当“加法”不适用时,可以考虑“减法”,能够有效提高做题的效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值