第一题:
题目大意:给出一个字符串,找出满足条件A的区间的个数。A:字符A,B,C的出现次数相同。 都出现0次也算,区间的长度可以是0(就是只有一个数).
30% |S| ≤ 100 。
70% |S| ≤ 1000 。
100% 1 ≤ |S| ≤ 1000000 。
解题过程:
1.考场上想不出AC算法,但是70分是很好拿的,最先想到先求出A,B,C出现次数的前缀和,枚举区间的两个端点,O(1)时间判断,枚举O(n^2)。
2.一看后面的题目都不是很好写,就先来优化一下这题,由于只有A,B,C是有用的,所以把其他字母拿掉,并把每个有效字母(A,B,C)后面的无效字母的个数保存下来,然后方法和前面一样,加些细节处理,这样就可以把区间的长度大大缩短。但是实际证明,这样是在做无用功,还是只有70分,还不如直接朴素算法省力。
3.AC算法:假设区间[i,j]符合要求,那么SUMA[j]-SUMA[i-1]=SUMB[j]-SUMB[i-1]=SUMC[j]-SUMC[j-1],变形一下得到
SUMA[j]-SUMB[j]=SUMA[i-1]-SUMB[i-1];
SUMB[j]-SUMC[j]=SUMB[i-1]-SUMC[i-1];
也就是说 如果区间[i,j]符合要求,必须满足j和i-1的 A-B的个数相等,j和i-1的B-C的个数相等。
那么只要把一个点 描述成一个二元组{SUMA-SUMB,SUMB-SUMC}, 找到一个和它完全相等的,就可以当成一个符合要求的区间的两个端点。
那么只要把所有二元组排个序,以SUMA-SUMB为第一关键字,SUMB-SUMC为第二关键字。如果有连续的n个相等的二元组,那么就表示有n*(n-1)/2个合法区间,累加到答案里就好。
但是这样还不完善,这样是没法找出 区间长度为0的。 2种处理办法,一种是虚拟一个二元组{0,0},还有一种是 扫一遍,找出所有{0,0}的二元组,累加到ans。
成绩不是很理想,3个题目加起来才120分。
常州培训 day1 解题报告