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