题目描述
咕咕东很聪明,但他最近不幸被来自宇宙的宇宙射线击中,遭到了降智打击,他的英语水平被归 零了!这一切的始作俑者宇宙狗却毫不知情! 此时咕咕东碰到了一个好心人——TT,TT在吸猫之余教咕咕东学英语。今天TT打算教咕咕东字母A 和字母B,TT给了咕咕东一个只有大写A、B组成的序列,让咕咕东分辨这些字母。 但是咕咕东的其他学科水平都还在,敏锐的咕咕东想出一个问题考考TT:咕咕东问TT这个字符串 有多少个子串是Delicious的。 TT虽然会做这个问题,但是他吸完猫发现辉夜大小姐更新了,不想回答这个问题,并抛给了你, 你能帮他解决这个问题吗?
Delicious定义:对于一个字符串,我们认为它是Delicious的当且仅当它的每一个字符都属于一个 大于1的回文子串中。
输入描述
输入第一行一个正整数n,表示字符串长度 接下来一行,一个长度为n只由大写字母A、B构成的字符串。
输出描述
输出仅一行,表示符合题目要求的子串的个数。
样例输入
5
AABBB
样例输出
6
样例解释
对于该样例,符合条件的六个子串分别是:
数据组成
问题分析
这道题可能一看上去特别麻烦,刚开始以为是一道需要动态规化的题目,分析过后发现,字符串只有大写A、B组成的序列,我们可以将连续的A、B进行记录,开设a数组,a[i]代表第 i 段序列的长度(每段序列都是一样的字母组成,即由‘A’或‘B’组成)。则要求的Delicious子串的产生分为三种情况:
1.同一段序列产生的;
2.相邻的两段序列产生的;
3.至少由三段序列产生,即字符串中间有一段完整的小序列。
因此我们只需要枚举每一段序列即可求解,时间复杂度O(n)。
#include<stdio.h>
#include<string.h>
long long a[300010],sum[300010];
int main(){
int n,K=0;
char c,pre='C';
long long ans=0;
scanf("%d",&n);scanf("%c",&c);//读换行符
memset(a,0,sizeof a);
for(int i=0;i<n;i++){
scanf("%c",&c);
if(c!=pre){
pre=c;
K++;
}
a[K]++;
}
sum[0]=0;
for(int i=1;i<=K;i++)
sum[i]+=sum[i-1]+a[i];
for(int i=1;i<=K;i++)
ans+=a[i]*(a[i]-1)/2;
//printf("%lld\n",ans);
for(int i=2;i<=K;i++)
ans+=(a[i]-1)*(a[i-1]-1);
//printf("%lld\n",ans);
for(int i=3;i<=K;i++)
ans+=a[i]*sum[i-2];
printf("%lld",ans);
return 0;
}