转化与组合

对于一个只含有'a','b'字母的字符串s1,合并相邻且相同的字符之后如果得到的字符串s2为“回文串”,则称s1为“好串”。
回文串:对于长度为len的字符串s[0..len - 1],任意0≤i≤len都有 s[i] = s[len - i - 1],则s为回文串。
例如aaabba合并后为aba,aba为回文串,则原串aabba为“好串”。
现给定字符串s,求s包含多少个长度为偶数“好串”,多少个长度为奇数的“好串”。(好串在s中应为连续的一段子串) s的长度len范围(1<= len <= 100000);
输出ev_ans(偶数好串的个数) od_ans(奇数好串的个数);
 
思路解析:通过观察任意的相同的字符之间都是一个回文串。由于len最大值为100000,只能用O(n)级复杂度的算法,所以在读到第i位时要判断出第i位时ev_ans和od_ans的值;这样才能在复杂度允许下得出答案;首先我们要判断第i位为奇数位还是偶数位;然后通读读取到第i位,且与之相同字符在奇数位个数,与偶数位的个数来更新答案。
 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 const int MaxN = 1e5;
 6 char s[MaxN + 5];
 7 int len;
 8 long long od_a, od_b, od_ans, ev_a, ev_b, ev_ans;
 9 
10 int main()
11 {
12   scanf("%s", s);
13   len = strlen(s);
14   for(int i = 0; i <= len - 1; i++)
15   {
16     if(i & 1)
17     {
18       if(s[i] == 'a') 
19       {
20         od_a++;    
21         od_ans += od_a;   //如果i为奇数;则od_ans需增加od_a的个数;
22         ev_ans += ev_a;   //如果i为奇数;则ev_ans需增加ev_a的个数;
23       }
24       if(s[i] == 'b') 
25       {
26         od_b++;
27         od_ans += od_b;   
28         ev_ans += ev_b;  
29       }
30     }
31     else
32     {
33       if(s[i] == 'a')
34       {
35         ev_a++;
36         od_ans += ev_a;   //如果i为偶数;则od_ans需增加ev_a的个数;
37         ev_ans += od_a;   //如果i为偶数;则ev_ans需增加od_a的个数;
38       }
39       if(s[i] == 'b')
40       {
41         ev_b++;
42         od_ans += ev_b;
43         ev_ans += od_b;
44       }
45     }
46   }
47   printf("%I64d %I64d\n", ev_ans, od_ans);
48 }
View Code

本题重点在于读过1次的字符不能再次搜索,在每一位都更新答案,并记录到本位与本位字符相同的奇数位字符次数,和偶数位次数。

posted @ 2015-11-24 19:46  chen_jq  阅读(168)  评论(0)    收藏  举报