week12_csp模测_C 咕咕东学英语

题目

咕咕东很聪明,但他最近不幸被来自宇宙的宇宙射线击中,遭到了降智打击,他的英语水平被归 零了!这一切的始作俑者宇宙狗却毫不知情!
此时咕咕东碰到了一个好心人——TT,TT在吸猫之余教咕咕东学英语。今天TT打算教咕咕东字母A 和字母B,TT给了咕咕东一个只有大写A、B组成的序列,让咕咕东分辨这些字母
但是咕咕东的其他学科水平都还在,敏锐的咕咕东想出一个问题考考TT:咕咕东问TT这个字符串 有多少个子串是Delicious的。
TT虽然会做这个问题,但是他吸完猫发现辉夜大小姐更新了,不想回答这个问题,并抛给了你, 你能帮他解决这个问题吗?
Delicious定义:对于一个字符串,我们认为它是Delicious的当且仅当它的每一个字符都属于一个 大于1的回文子串中。

输入输出

Input

输入第一行一个正整数n,表示字符串长度 接下来一行,一个长度为n只由大写字母A、B构成的字符串。

Output

输出仅一行,表示符合题目要求的子串的个数。

Sample Input
5
AABBB
Sample Output
6

数据规模

在这里插入图片描述

思路分析

这道题考试的时候理解回文子串花了一些时间,然后找规律,最后没有足够时间来完成这道题目。补题时最先想到的是暴力枚举,复杂度是O(n^2),显然后四个测试点过不去,要么考虑剪枝,要么……换个思路。
鉴于不合法的子串只有AB…B、BA……A、A……AB、B……BA这四种类型,可以考虑求出所有子串个数(n*(n-1)/2),然后减去不合法子串的个数即可。
那么如何求不合法子串的个数呢?拿AAAAB举个栗子,该字符串是典型的不合法结构,可以发现,子串AAAAB是不合法的,同理,子串AAAB、AAB、AB也是不合法的,因此,不合法子串的个数就等于字符A的个数。同理,AB……B和B……B A结构中不合法子串的个数是字符B的个数,但是要注意,对于两种字符串衔接处的AB或BA被计算了两次,因此总数减一,得到不合法子串的个数为numA+numB-1。
具体做法:寻找连续的字符,当遇到不同字符时分段记录前后两种字符的个数。

总结反思

考场上要放平心态,找规律的题目别心急,静心思考。

AC代码

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

string s;
long long n,ans=0,l=0,r=0,cnt1=0,cnt2=0,no=0;
//cnt1表示前一段字符的个数,cnt2表示后一段字符的个数,no表示不合法子串个数
int main()
{
	cin>>n;
	cin>>s;
	ans=n*(n-1)/2;//ans初始化为总字符串个数
        while(l<n){
   		r=l;
  		while(r<n-1&&s[r]==s[l]){
  		    r++;
  		}
  		if(r==n-1&&s[r]==s[l]) break;
  		cnt1=r-l;//前一段字符的个数
  		char c=s[r];
  		long long tmp=r; 
  		while(r<n-1&&s[r]==c){
  		    r++;
  		}
  		if(r==n-1&&s[r]==c) 
   		    cnt2=r-tmp+1;
   	 	//r记录下次变化的位置,因此如果r没遍历到最后一个,
   		//那么长度就是r-tmp,即不包括位置r的字符	      
  		else 
  		    cnt2=r-tmp;
 		l=tmp;
  		no+=cnt1+cnt2-1;//不合法子串个数
 	}   
 	ans-=no;
 	cout<<ans<<endl;
 	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值