Codeforces 1084C - The Fair Nut and String
题目连接
Codeforces 1084C - The Fair Nut and String
题目大意
给出一个字符串,查找有多少个被b隔开的a的子串。如a
、aba
,abba
,abbbba
等都是合法的,但aa
是非法的。
但要注意的是aba
,abba
,abbbbbba
等在统计的过程中只计算一个。
做法
开始思路(错误)
一开始读错题了,想着前缀和统计出来a的个数,对于遇到一串b,答案就加上:这串b前面的a个个数乘这串b后面的a的个数。 然后再加上所有a的个数(考虑单独的a)。
这样的做法WA在了第十组测试用例上。
考虑到我这种做法只能解决单独的a和abba
等这种情况,难以解决如ababa
这种情况,于是gg。
AC思路
首先很显然,删除除了a和b以外的字符(对于一开始的错误做法,删不删没啥影响)。
之后我们统计被b隔开的a的情况,存到一个数组中。 如abbaaabaa
,存到数组中变成[1,3,2]
的形式。
这样我们就可以把abbaaabaa
的情况简化成ababa
的情况。 接下来我们考虑ababa
的情况:
- 初始化
ans = 0
- 对于第一个
a
,答案是1(自身)
,ans = 1
- 对于
b
跳过(下同) - 考虑前两个
a
,答案是1(自身) + 1(加上前面对应的1)
,ans = 2
; - 对于前三个
a
,答案是1(自身) + 2(加上前面对应的两个2
) ,ans = 3
; - 最终答案是3个,分别是
[1],[3],[5],[1,3],[1,3],[1,5]
。
- 很显然的容易发现
ans = lastans + 1
但是考虑到,我们之前把很多a压缩成了1个(即把abbaaabaa
变成了ababa
),在这里把b缩成一个是没有影响的。
但是对于a却影响了答案,如何解决这个问题呢?
观察到每个a其实都是找之前被b隔开的a,而两个b之间夹着的一串a之间是互相不影响的。
那么我们其实只要乘上这个一串a的个数就好了。即对于abbaaabaa
:
- 初始化
ans = 0
- 对于第一个
a
,答案是1(自身)
,ans = 1
- 对于
b
跳过(下同) - 考虑第二串
a
的第一个a
,答案是1(自身) + 1(加上第一串的一个a)
,ans = 2
; - 考虑第二串
a
的第二个a
,答案是1(自身) + 1(加上第一串的一个a)
,ans = 3
; - 考虑第二串
a
的第三个a
,答案是1(自身) + 1(加上第一串的一个a)
,ans = 4
; - …………
- 即就是
1(自身) + 1(之前对应的第一串的一个a) * 3(这一串a的个数) )
- 很显然的容易发现
ans = ( lastans + 1 ) * 这一串a的个数
到这里,答案也就呼之欲出了(也可能是叽里呱啦一堆,语无伦次让人一头雾水2333)。
具体看代码吧。
官方题解思路
官方题解的思路是,对于每一串a看成一个集合,如abaaabbaaaa
,就可以看做是有三个集合,三个集合的元素个数分别为[1,3,4]
那么答案可以看做是从每一个集合中可以选取0到任意个。
所以答案就是所有集合元素个数+1再相乘,即245个。
考虑到会有一种是全零的情况(即一个都没有选),所以他最终答案再减去1。
这种思路可能更好理解一点?
代码
1 |
|