[题目传送门] http://www.codeforces.com/problemset/problem/451/D
[题目大意]
给你一个长度最长为100000的只含有a和b的字符串。这个字符串允许一种“压缩”,相邻的相同的字符可以被缩成一个字符。比如字符串aabb可以被缩成最简ab。
接下来如按照题目中的意思来理解比较混乱。简单的说,原来的字符串中要找到有多少个压缩后是回文的子串,还要求分是奇数长度还是偶数长度。
[分析]
这里很容易发现一个结论,就是压缩前如果是一个回文串,压缩后一定也是,但是压缩前如果不是,压缩后仍然可能是一个回文串。所以其实我们只要考虑压缩后的情况。
这里分成四类:
1. 原字符串中是偶数长度的,两头由a结尾的。
2. 原字符串中是偶数长度的,两头由b结尾的。
3. 原字符串中是奇数长度的,两头由a结尾的。
4. 原字符串中是奇数长度的,两头由b结尾的。
考虑第一类,要知道,如果仅考虑压缩后的情况,满足1条件的回文串一定长成 aba , ababa 这样。接下来证明一个结论,出现在原字符串偶数位的a,和任意一个出现在奇数位的a,配对后的字串一定回文。
简单证明:
形如a...a 的字串 一定可以缩成 ab....ba 或 aba 后者已经是一个回文,证明前者是否一定是个回文,前者一定可以压缩为 aba....aba 或 ababa 。可以一直递推下去,因为原来字符串中,前后两个a一个在奇数位,一个在偶数位,所以原字符串中的这个字串是偶数的长度。 证明结束。
其实递推到第二步时就可以发现形如ab...ba 这里的两个b也是一个在奇数位一个在偶数位,相当于证明 一个在奇数位b和一个在偶数位的b形如b....b一定回文。最后总能缩到一个程度,使其回文。
第二类同第一类。
考虑第三类,证明结论 : 任意两个奇数位a结尾的形如 a.....a 的子串一定回文。 任意两个偶数位a结尾的形如 a....a 的子串一定回文。
简单参考上面的证明:
形如a....a 的子串一定可以缩成 ab....ba 或 aba , 后者已经回文。 前者可以不停递推到回文。
由于原来字符串中,两个结尾的a要么都是奇数位要么都是偶数位,所以原来字符串中的长度一定是奇数。
第四类同第三类。
另外单独一个字符都是奇数回文,所以再加上字符串的长度。
[代码君]
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 string in; 5 int main(){ 6 cin >> in; 7 long long a0 = 0 , a1 = 0; 8 long long b0 = 0 , b1 = 0; 9 int len = in.size(); 10 for (int i = 0; i < len; i++) { 11 if (i % 2) { 12 in[i] == 'a' ? a1++ : b1++; 13 } 14 else in[i] == 'a' ? a0++ : b0++; 15 } 16 long long ans1 = a0 * a1 + b0 * b1; 17 long long ans2 = (a0 * (a0 - 1) / 2) + (a1 * (a1 - 1) / 2) + (b0 * (b0 - 1) / 2) + (b1 * (b1 - 1) / 2) + len; 18 cout << ans1 << " " << ans2 << endl; 19 return 0; 20 }