好序列

我們把一個好的字符串的定義爲,如果合併了所有連續的相等字符,得到的
字符串是迴文。
例如,“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^2+Cq2C_q^2+(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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章