题目
分析
delicious的定义:当且仅当它的每一个字符都属于一个大于1的回文子串中。
正向求出子字符串符合delicious的不好求,我们思考一下,逆向的求出不符合delicious的子字符串区间。如AB、AAB、AAAB、AA…B或者BA、BBA、BBBA、BB…A这样的是不符合delicious的,其他的都符合。
这样问题就转换成了一个字符串里面有多少不符合的子串。
用A_num代表正在遍历的这段子串A的个数,B_num表示正在遍历的这段子串B的个数。p始终指向遍历的这段的开头,然后循环遍历整个字符串。如果遇到了和p不同的(也就是AB\ABB…其中的),就用总的子串减去相应的子串个数。
最后注意的是:因为是遇到不同的才开始减去,那么最后一段是没有处理的,所以需要最后处理一下(A_num>0&&B_num>0)。
代码
#include<stdio.h>
#include<string.h>
char a[10000000];
int main()
{
//读入输入数据
long long n;
scanf("%lld",&n);
getchar();
for(int i=0;i<n;i++)
scanf("%c",&a[i]);
long long A_num=0,B_num=0;
long long tot=n*(n-1)/2;//任意取两个数作为区间的端点
char p=a[0];//p始终是遍历的上一个不同的
if(a[0]=='A') A_num++;//A_num代表一个字串中A的数目,
else B_num++;
for(int i=1;i<n;i++)
{
if(p!=a[i])//如:AB AAB AAAB / BA BBA BBBA
{
if(B_num>0&&A_num>0)
{
tot-=(A_num+B_num-1);
if(a[i]=='A') A_num=0;//新的字串,进行更新
else B_num=0;
}
p=a[i];
}
if(a[i]=='A') A_num++;
else B_num++;
}
if(B_num>0&&A_num>0)
{
tot-=(A_num+B_num-1);
}
printf("%lld\n",tot);
}