我们把一个好的字符串的定义为,如果合并了所有连续的相等字符,得到的
字符串是回文。
例如,“aabbbaa”是好的字符串,因为合并后的步骤将变成“aba”。
给定一个字符串,必须找到两个值:
偶数长度的好的子串数;
奇数长度的好的子串数。
★数据输入
输入的第一行包含一个长度为 n 的单一字符串
字符串的每个字符将是’a’或’b’。
字符长度 n
30 % 的数据 1 <= n <= 1000
100 % 的数据 1 <= n <= 100000
★数据输出
第一行输出偶数长度的好的子串数,奇数长度的好的子串数,以空格隔开
输入示例 输出示例
bb 1 2
输入示例 输出示例
baab 2 4
输入示例 输出示例
babb 2 5
★HINT 一个字符串是回文,当且仅当把这个字符串翻转后,还和原串一致。
比如“aba”、“abba”是回文串,而“abc”,“abab”就不是。
观察可知,其实最终的好序列必定是
abababababababab…
或者
babababbabab…
中的一个,并且,去重后的序列长度肯定为奇数长度。
所以只要一个原串的首尾相同,就意味着它去重后一定是回文串,因此,我们只需要统计一下有多少个’a’和多少个’b’就能算出有多少个好序列。假设有p个’a’,有q个’b’,则可以组成的好的序列有:
Cp2C_p^2Cp2+Cq2C_q^2Cq2+(p+q)
至于原串是奇数还是偶数则要看起始下标和末尾下标的情况了
例如:
a b a a b a b a
对应下标:
1 2 3 4 5 6 7 8
那么由第一个a到第二个a之间的字符所组成的字符串是 aba 长度为(3-1)+1=3为奇数
其实可以看到,因为要把两个端点算进去,所以这里 奇数下标-奇数下标 得到的是奇数长度的串,同样偶数下标-偶数下标 得到的数奇数长度的串,而偶数下标-奇数下标 和 奇数下标-偶数下标 都得到偶数长度的串,因此,奇数下标的a搭配偶数下标的a和奇数下标的b搭配偶数下标的b就得到了所求的字符串长度为偶数的数量
代码:
#pragma warning(disable:4996)
#include <stdio.h>
#include<string.h>
typedef long long ll;
typedef unsigned long long ull;
#define e 2.718281828459
#pragma warning(disable:4996)
#define sf scanf
#define pf printf
#define sf2d(x,y) scanf("%d %d",&(x),&(y))
#define sfd(x) scanf("%d",&x)
#define sff(p) scanf("%lf",&p)
#define pfd(x) printf("%d\n",x)
#define mset(x,b) memset((x),b,sizeof(x))
int main(void) {
char ch;
int suma = 0, sumb = 0;//ab总个数
int pra=0, prb=0;//奇数位置
int evena=0, evenb=0;//偶数位置
int cnt = 0;
while (ch = getchar(), (ch=='a'||ch=='b')) {
cnt++;
if (ch == 'a') {
suma++;//统计a的个数
if (cnt & 1)
pra++;//奇数位置的a的个数
else
evena++;//偶数位置的a的个数
}
else {
sumb++;
if (cnt & 1)
prb++;
else
evenb++;
}
}
int presum = suma + sumb + (pra - 1)*pra / 2 + evena * (evena - 1) / 2 + prb * (prb - 1) / 2 + evenb * (evenb - 1) / 2;//奇数长度的串,组合数
int evensum = pra * evena + prb * evenb;//偶数长度的串
pf("%d %d\n", evensum, presum);
return 0;
}